刘光城 發表於 2022-3-13 21:04:00

go smtp示例

<p><span data-cke-copybin-start="1"><span data-cke-copybin-start="1">​</span></span>书接上文<span class="cke_widget_wrapper cke_widget_inline cke_widget_csdnlink cke_widget_wrapper_link-info cke_widget_selected" data-cke-display-name="a" data-cke-filter="off" data-cke-widget-id="0" data-cke-widget-wrapper="1">邮件实现详解,这里我们及我们简单复习一下smtp的指令如下:</span></p>
<div class="cnblogs_code">
<pre>telnet smtp.<span style="color: rgba(128, 0, 128, 1)">163</span>.com <span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">

ehlo dz45693

auth login

输入用户名base64

输入密码base64
mail </span><span style="color: rgba(0, 0, 255, 1)">from</span>:&lt;dz45693@<span style="color: rgba(128, 0, 128, 1)">163</span>.com&gt;<span style="color: rgba(0, 0, 0, 1)">

rcpt to:</span>&lt;dz45693@sina.com&gt;<span style="color: rgba(0, 0, 0, 1)">

data

</span><span style="color: rgba(0, 0, 255, 1)">from</span>:&lt;dz45693@<span style="color: rgba(128, 0, 128, 1)">163</span>.com&gt;<span style="color: rgba(0, 0, 0, 1)">
to:</span>&lt;dz45693@sina.com&gt;<span style="color: rgba(0, 0, 0, 1)">
subject:hello world

This </span><span style="color: rgba(0, 0, 255, 1)">is</span> the first email sent by hand <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> the SMTP protocol
.
quit  </span></pre>
</div>
<p><span data-cke-copybin-start="1"><span data-cke-copybin-end="1">​<img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313182841054-2068185709.png"></span></span></p>
<p>好,那我们下现在用go实现代码让如下: 这里只是一个demo,主要熟悉smtp命令</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">package main

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bufio</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">encoding/base64</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fmt</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">strconv</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">strings</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)


func main() {
    testSmtp()
}

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)"> gConn net.Conn
</span><span style="color: rgba(0, 0, 255, 1)">var</span> gRead *<span style="color: rgba(0, 0, 0, 1)">bufio.Reader
</span><span style="color: rgba(0, 0, 255, 1)">var</span> gWrite *<span style="color: rgba(0, 0, 0, 1)">bufio.Writer

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">可以放到这样的类里</span>
type TcpClient <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> {
    Connnet.Conn
    Read</span>*<span style="color: rgba(0, 0, 0, 1)">bufio.Reader
    Write </span>*<span style="color: rgba(0, 0, 0, 1)">bufio.Writer
} </span><span style="color: rgba(0, 128, 0, 1)">//
</span><span style="color: rgba(0, 0, 0, 1)">
func Connect(host </span><span style="color: rgba(0, 0, 255, 1)">string</span>, port <span style="color: rgba(0, 0, 255, 1)">int</span>) (net.Conn, *bufio.Reader, *<span style="color: rgba(0, 0, 0, 1)">bufio.Writer) {
    addr :</span>= host + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> strconv.Itoa(port)
    conn, err :</span>= net.Dial(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tcp</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, addr)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, nil, nil
    }

    reader :</span>=<span style="color: rgba(0, 0, 0, 1)"> bufio.NewReader(conn)
    writer :</span>=<span style="color: rgba(0, 0, 0, 1)"> bufio.NewWriter(conn)

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> conn, reader, writer
} </span><span style="color: rgba(0, 128, 0, 1)">//</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行,可再优化</span>
func RecvLine() <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> {
    line, err :</span>= gRead.ReadString(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">'</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如何设定超时?</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      fmt.Print(err)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">
    }

    line </span>= strings.Split(line, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 128, 1)">0</span>] <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">还要再去掉 "\r",其实不去掉也可以</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> line
}

func SendLine(line </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) {
    gWrite.WriteString(line </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    gWrite.Flush()
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">解码一行命令,这里比较简单就是按空格进行分隔就行了</span>
func DecodeCmd(line <span style="color: rgba(0, 0, 255, 1)">string</span>, sp <span style="color: rgba(0, 0, 255, 1)">string</span>) []<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> {
    tmp :</span>=<span style="color: rgba(0, 0, 0, 1)"> strings.Split(line, sp)
    </span><span style="color: rgba(0, 0, 255, 1)">var</span> cmds = []<span style="color: rgba(0, 0, 255, 1)">string</span>{<span style="color: rgba(128, 0, 0, 1)">""</span>, <span style="color: rgba(128, 0, 0, 1)">""</span>, <span style="color: rgba(128, 0, 0, 1)">""</span>, <span style="color: rgba(128, 0, 0, 1)">""</span>, <span style="color: rgba(128, 0, 0, 1)">""</span>} <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">先定义多几个,以面后面使用时产生异常</span>
    <span style="color: rgba(0, 0, 255, 1)">for</span> i := <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; len(tmp); i++<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> i &gt;=<span style="color: rgba(0, 0, 0, 1)"> len(cmds) {
            </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
      }
      cmds </span>=<span style="color: rgba(0, 0, 0, 1)"> tmp
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> cmds
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取多行结果</span>
func RecvMCmd() <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> {
    i :</span>= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
    rs :</span>= <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">
    mLine :</span>= <span style="color: rgba(128, 0, 0, 1)">""</span>
    <span style="color: rgba(0, 0, 255, 1)">for</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; <span style="color: rgba(128, 0, 128, 1)">50</span>; i++<span style="color: rgba(0, 0, 0, 1)"> {
      rs </span>= RecvLine() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">只收取一行</span>
      mLine = mLine + rs + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> len(rs) &lt; <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
      } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">长度要足够</span>
      c4 := rs[<span style="color: rgba(128, 0, 128, 1)">4</span>-<span style="color: rgba(128, 0, 128, 1)">1</span>] <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第4个字符</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(128, 0, 0, 1)">'</span> ==<span style="color: rgba(0, 0, 0, 1)"> c4 {
            </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
      } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第4个字符是空格就表示读取完了</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">也可以判断 "250[空格]"</span>
<span style="color: rgba(0, 0, 0, 1)">    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mLine
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">简单的测试一下 smtp</span>
<span style="color: rgba(0, 0, 0, 1)">func testSmtp() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">连接</span>
    gConn, gRead, gWrite = Connect(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smtp.163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">)
    defer gConn.Close()
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line :=<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">解码一下,这样后面的 EHLO 才能有正确的第二个参数</span>
    cmds := DecodeCmd(line, <span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    domain :</span>= cmds[<span style="color: rgba(128, 0, 128, 1)">1</span>] <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要从对方的应答中取出域名</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">空格分开的各个命令参数中的第二个

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">发送一个命令</span>
    SendLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EHLO</span><span style="color: rgba(128, 0, 0, 1)">"</span> + <span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(128, 0, 0, 1)">"</span> + domain) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">domain 要求其实来自 HELO 命令</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">HELO &lt;SP&gt; &lt;domain&gt; &lt;CRLF&gt;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取多行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvMCmd()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">--------------------------------------------------
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用 base64 登录</span>
    SendLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AUTH LOGIN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    s :</span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要换成你的用户名,注意 163 邮箱的话不要带后面的 @域名 部分</span>
    s = base64.StdEncoding.EncodeToString([]<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">(s))
    SendLine(s)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    s </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xxxxx</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要换成您的密码</span>
    s = base64.StdEncoding.EncodeToString([]<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">(s))
    SendLine(s)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">--------------------------------------------------
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">邮件内容</span>
    <span style="color: rgba(0, 0, 255, 1)">from</span> := <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    to :</span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@sina.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">

    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">MAIL FROM: &lt;</span><span style="color: rgba(128, 0, 0, 1)">"</span> + <span style="color: rgba(0, 0, 255, 1)">from</span> + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注意"&lt;" 符号和前面的空格。空格在协议中有和没有都可能,最好还是有
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RCPT TO: &lt;</span><span style="color: rgba(128, 0, 0, 1)">"</span> + to + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DATA</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">发送邮件头</span>
    SendLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">from:&lt;dz45693@163.com&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">to:&lt;dz45693@sina.com&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">subject:hello world</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">""</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">发送空行 后面就是邮件体</span>
    SendLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">This is the first email sent by hand using the SMTP protocol</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)

    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">.</span><span style="color: rgba(128, 0, 0, 1)">"</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">邮件结束符

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收取一行</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)

    SendLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">quit</span><span style="color: rgba(128, 0, 0, 1)">"</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">链接推出</span>
    line =<span style="color: rgba(0, 0, 0, 1)"> RecvLine()
    fmt.Println(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">recv:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> line)
} </span><span style="color: rgba(0, 128, 0, 1)">//</span></pre>
</div>
<p>运行结果图下:</p>
<p><img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313183143346-1687104986.png"></p>
<p>&nbsp;在go的sdk中提供了SendMail方法【<strong>发送邮件后这个方法会关闭链接</strong>】,实现如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313183749101-1222709924.png"></p>
<p>实现如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">func SendMailBySmtp(){
    auth :</span>= smtp.PlainAuth(<span style="color: rgba(128, 0, 0, 1)">""</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xxx</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smtp.163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    to :</span>= []<span style="color: rgba(0, 0, 255, 1)">string</span>{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@sina.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
    image,_:</span>=ioutil.ReadFile(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">d:\\Downloads\\1.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    imageBase64:</span>=<span style="color: rgba(0, 0, 0, 1)">base64.StdEncoding.EncodeToString(image)
    msg :</span>= []<span style="color: rgba(0, 0, 255, 1)">byte</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">from:dz45693@163.com\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">to: dz45693@sina.com\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span> +
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Subject: hello,subject!\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Content-Type:multipart/mixed;boundary=a\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Mime-Version:1.0\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span> +
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--a\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Content-type:text/plain;charset=utf-8\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Content-Transfer-Encoding:quoted-printable\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">此处为正文内容!\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--a\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Content-type:image/jpg;name=1.jpg\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Content-Transfer-Encoding:base64\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+<span style="color: rgba(0, 0, 0, 1)">
      imageBase64</span>+<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>+
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--a--\r\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    err :</span>= smtp.SendMail(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smtp.163.com:25</span><span style="color: rgba(128, 0, 0, 1)">"</span>, auth, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, to, msg)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      fmt.Println(err)
    }
}</span></pre>
</div>
<p>运行效果</p>
<p><img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313184550091-406229720.png"></p>
<p>&nbsp;</p>
<p>&nbsp;示例如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">func SendMailByGomailOne(){
    m :</span>=<span style="color: rgba(0, 0, 0, 1)"> gomail.NewMessage()
    m.SetAddressHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">From</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">To</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@sina.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Subject</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello SendMailByGomailOne!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.Embed(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">d:\\Downloads\\1.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetBody(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/html</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">此处为正文121333!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)

    d :</span>= gomail.NewDialer(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smtp.163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">25</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xxxx#</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err := d.DialAndSend(m); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      panic(err)
    }
}</span></pre>
</div>
<p>运行结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313185335209-1879091795.png"></p>
<p>来我们看看DialAndSend的实现如下:&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">package gomail

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">crypto/tls</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fmt</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">io</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net/smtp</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">strings</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">time</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> A Dialer is a dialer to an SMTP server.</span>
type Dialer <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Host represents the host of the SMTP server.</span>
    Host <span style="color: rgba(0, 0, 255, 1)">string</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Port represents the port of the SMTP server.</span>
    Port <span style="color: rgba(0, 0, 255, 1)">int</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Username is the username to use to authenticate to the SMTP server.</span>
    Username <span style="color: rgba(0, 0, 255, 1)">string</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Password is the password to use to authenticate to the SMTP server.</span>
    Password <span style="color: rgba(0, 0, 255, 1)">string</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Auth represents the authentication mechanism used to authenticate to the
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> SMTP server.</span>
<span style="color: rgba(0, 0, 0, 1)">    Auth smtp.Auth
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> SSL defines whether an SSL connection is used. It should be false in
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> most cases since the authentication mechanism should use the STARTTLS
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> extension instead.</span>
    SSL <span style="color: rgba(0, 0, 255, 1)">bool</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TSLConfig represents the TLS configuration used for the TLS (when the
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> STARTTLS extension is used) or SSL connection.</span>
    TLSConfig *<span style="color: rgba(0, 0, 0, 1)">tls.Config
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> LocalName is the hostname sent to the SMTP server with the HELO command.
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> By default, "localhost" is sent.</span>
    LocalName <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> NewDialer returns a new SMTP Dialer. The given parameters are used to connect
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> to the SMTP server.</span>
func NewDialer(host <span style="color: rgba(0, 0, 255, 1)">string</span>, port <span style="color: rgba(0, 0, 255, 1)">int</span>, username, password <span style="color: rgba(0, 0, 255, 1)">string</span>) *<span style="color: rgba(0, 0, 0, 1)">Dialer {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> &amp;<span style="color: rgba(0, 0, 0, 1)">Dialer{
      Host:   host,
      Port:   port,
      Username: username,
      Password: password,
      SSL:      port </span>== <span style="color: rgba(128, 0, 128, 1)">465</span><span style="color: rgba(0, 0, 0, 1)">,
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> NewPlainDialer returns a new SMTP Dialer. The given parameters are used to
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> connect to the SMTP server.
</span><span style="color: rgba(0, 128, 0, 1)">//</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Deprecated: Use NewDialer instead.</span>
func NewPlainDialer(host <span style="color: rgba(0, 0, 255, 1)">string</span>, port <span style="color: rgba(0, 0, 255, 1)">int</span>, username, password <span style="color: rgba(0, 0, 255, 1)">string</span>) *<span style="color: rgba(0, 0, 0, 1)">Dialer {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> NewDialer(host, port, username, password)
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Dial dials and authenticates to an SMTP server. The returned SendCloser
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> should be closed when done using it.</span>
func (d *<span style="color: rgba(0, 0, 0, 1)">Dialer) Dial() (SendCloser, error) {
    conn, err :</span>= netDialTimeout(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tcp</span><span style="color: rgba(128, 0, 0, 1)">"</span>, addr(d.Host, d.Port), <span style="color: rgba(128, 0, 128, 1)">10</span>*<span style="color: rgba(0, 0, 0, 1)">time.Second)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> d.SSL {
      conn </span>=<span style="color: rgba(0, 0, 0, 1)"> tlsClient(conn, d.tlsConfig())
    }

    c, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> smtpNewClient(conn, d.Host)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> d.LocalName != <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> err := c.Hello(d.LocalName); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, err
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> !<span style="color: rgba(0, 0, 0, 1)">d.SSL {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> ok, _ := c.Extension(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">STARTTLS</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); ok {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> err := c.StartTLS(d.tlsConfig()); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
                c.Close()
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, err
            }
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> d.Auth == nil &amp;&amp; d.Username != <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> ok, auths := c.Extension(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AUTH</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); ok {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> strings.Contains(auths, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CRAM-MD5</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) {
                d.Auth </span>=<span style="color: rgba(0, 0, 0, 1)"> smtp.CRAMMD5Auth(d.Username, d.Password)
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> strings.Contains(auths, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">LOGIN</span><span style="color: rgba(128, 0, 0, 1)">"</span>) &amp;&amp;
                !strings.Contains(auths, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PLAIN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) {
                d.Auth </span>= &amp;<span style="color: rgba(0, 0, 0, 1)">loginAuth{
                  username: d.Username,
                  password: d.Password,
                  host:   d.Host,
                }
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                d.Auth </span>= smtp.PlainAuth(<span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">, d.Username, d.Password, d.Host)
            }
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> d.Auth !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> err = c.Auth(d.Auth); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
            c.Close()
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil, err
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">return</span> &amp;<span style="color: rgba(0, 0, 0, 1)">smtpSender{c, d}, nil
}

func (d </span>*Dialer) tlsConfig() *<span style="color: rgba(0, 0, 0, 1)">tls.Config {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> d.TLSConfig ==<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> &amp;<span style="color: rgba(0, 0, 0, 1)">tls.Config{ServerName: d.Host}
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> d.TLSConfig
}

func addr(host </span><span style="color: rgba(0, 0, 255, 1)">string</span>, port <span style="color: rgba(0, 0, 255, 1)">int</span>) <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> fmt.Sprintf(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%s:%d</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, host, port)
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> DialAndSend opens a connection to the SMTP server, sends the given emails and
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> closes the connection.</span>
func (d *Dialer) DialAndSend(m ...*<span style="color: rgba(0, 0, 0, 1)">Message) error {
    s, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> d.Dial()
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
    }
    defer s.Close()

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Send(s, m...)
}

type smtpSender </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> {
    smtpClient
    d </span>*<span style="color: rgba(0, 0, 0, 1)">Dialer
}

func (c </span>*smtpSender) Send(<span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(0, 0, 255, 1)">string</span>, to []<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">, msg io.WriterTo) error {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err := c.Mail(<span style="color: rgba(0, 0, 255, 1)">from</span>); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> err ==<span style="color: rgba(0, 0, 0, 1)"> io.EOF {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> This is probably due to a timeout, so reconnect and try again.</span>
            sc, derr :=<span style="color: rgba(0, 0, 0, 1)"> c.d.Dial()
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> derr ==<span style="color: rgba(0, 0, 0, 1)"> nil {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> s, ok := sc.(*<span style="color: rgba(0, 0, 0, 1)">smtpSender); ok {
                  </span>*c = *<span style="color: rgba(0, 0, 0, 1)">s
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span> c.Send(<span style="color: rgba(0, 0, 255, 1)">from</span><span style="color: rgba(0, 0, 0, 1)">, to, msg)
                }
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">for</span> _, addr :=<span style="color: rgba(0, 0, 0, 1)"> range to {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> err := c.Rcpt(addr); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
      }
    }

    w, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> c.Data()
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> _, err = msg.WriteTo(w); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      w.Close()
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> w.Close()
}

func (c </span>*<span style="color: rgba(0, 0, 0, 1)">smtpSender) Close() error {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> c.Quit()
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Stubbed out for tests.</span>
<span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)"> (
    netDialTimeout </span>=<span style="color: rgba(0, 0, 0, 1)"> net.DialTimeout
    tlsClient      </span>=<span style="color: rgba(0, 0, 0, 1)"> tls.Client
    smtpNewClient</span>= func(conn net.Conn, host <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) (smtpClient, error) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> smtp.NewClient(conn, host)
    }
)

type smtpClient </span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> {
    Hello(</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) error
    Extension(</span><span style="color: rgba(0, 0, 255, 1)">string</span>) (<span style="color: rgba(0, 0, 255, 1)">bool</span>, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">)
    StartTLS(</span>*<span style="color: rgba(0, 0, 0, 1)">tls.Config) error
    Auth(smtp.Auth) error
    Mail(</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) error
    Rcpt(</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) error
    Data() (io.WriteCloser, error)
    Quit() error
    Close() error
}</span></pre>
</div>
<p>&nbsp;DialAndSend ,首先调用Dial方法创建连接,然后发送邮件,最后关闭链接,如果要频繁发邮件,那么是否保持长连接更好了?这里的Dial 调用了smtp.NewClient 创建smtp.Client对象c,然后调用c.Hello ,c.Auth,send 实际是调用c.Mail,c.Rcpt,c.Data,那么我们可以自己调用Dial方法 然后循环调用send方法,最后在close。</p>
<p>代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">func SendMailByGomailTwo() {
    d :</span>= gomail.NewDialer(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smtp.163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">25</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"xxx</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m :</span>=<span style="color: rgba(0, 0, 0, 1)"> gomail.NewMessage()
    m.SetAddressHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">From</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">To</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@sina.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Subject</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello SendMailByGomailtwo!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.Embed(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">d:\\Downloads\\1.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetBody(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/html</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">此处为正文121333!SendMailByGomailtwo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)

    s, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> d.Dial()
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      panic(err)
    }
    defer s.Close()

    err </span>=<span style="color: rgba(0, 0, 0, 1)"> gomail.Send(s, m)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      panic(err)
    }

    m.Reset()
    m.SetAddressHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">From</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@163.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">To</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dz45693@sina.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetHeader(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Subject</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello SendMailByGomailthree!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.Embed(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">d:\\Downloads\\2.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    m.SetBody(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/html</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">此处为正文1SendMailByGomailthreeSendMailByGomailthree!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    err </span>=<span style="color: rgba(0, 0, 0, 1)"> gomail.Send(s, m)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      panic(err)
    }
}</span></pre>
</div>
<p>运行结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/209993/202203/209993-20220313210346649-2056745953.png"></p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    windows技术爱好者<br><br>
来源:https://www.cnblogs.com/majiang/p/16001409.html
頁: [1]
查看完整版本: go smtp示例