全部产品
Search
文档中心

Direct Mail:Panggil SMTP menggunakan Go: Kode contoh

更新时间:Nov 10, 2025

Gunakan Port 80

Anda dapat menggunakan bahasa Go untuk mengirim email melalui SMTP. Kode ini telah diverifikasi pada Go versi 1.16.5.

Catatan

Untuk menggunakan Enkripsi TLS pada Port 465, lihat bagian di bawah ini. Jangan gunakan kode untuk Port 80 untuk tujuan ini.

package main

import (
    "fmt"
    "net/smtp"
    "strings"
		"time"
)

func SendToMail(user, password, host, subject, date, body, mailtype, replyToAddress string, to, cc, bcc []string) error {
    hp := strings.Split(host, ":")
    auth := smtp.PlainAuth("", user, password, hp[0])
    var content_type string
    if mailtype == "html" {
        content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
    } else {
        content_type = "Content-Type: text/plain" + "; charset=UTF-8"
    }

    cc_address := strings.Join(cc, ";")
    bcc_address := strings.Join(bcc, ";")
    to_address := strings.Join(to, ";")
    msg := []byte("To: " + to_address + "\r\nFrom: " + user + "\r\nSubject: " + subject+ "\r\nDate: " + date + "\r\nReply-To: " + replyToAddress + "\r\nCc: " + cc_address + "\r\nBcc: " + bcc_address + "\r\n" + content_type + "\r\n\r\n" + body)
    send_to := MergeSlice(to, cc)
    send_to = MergeSlice(send_to, bcc)
    err := smtp.SendMail(host, auth, user, send_to, msg)
    return err
}

func main() {
    user := "The sender address created in the console"
    password := "The SMTP password set in the console"
    host := "smtpdm.aliyun.com:80"
    to := []string{"recipient_address","recipient_address_1"}
    cc := []string{"cc_address","cc_address_1"}
    bcc := []string{"bcc_address","bcc_address_1"}
    subject := "test Golang to sendmail"
		date := fmt.Sprintf("%s", time.Now().Format(time.RFC1123Z))
    mailtype :="html"
    replyToAddress:="a***@example.net"
    body := "<html><body><h3>Test send to email</h3></body></html>"
    fmt.Println("send email")
    err := SendToMail(user, password, host, subject,date, body, mailtype, replyToAddress, to, cc, bcc)
    if err != nil {
        fmt.Println("Send mail error!")
        fmt.Println(err)
    } else {
        fmt.Println("Send mail success!")
    }
}

func MergeSlice(s1 []string, s2 []string) []string {
    slice := make([]string, len(s1)+len(s2))
    copy(slice, s1)
    copy(slice[len(s1):], s2)
    return slice
}
Catatan

Jika Anda menggunakan Go versi 1.9.2, mungkin terjadi kesalahan "koneksi tidak terenkripsi" karena versi tersebut memerlukan autentikasi terenkripsi. Untuk mengatasi masalah ini, gunakan autentikasi LOGIN dengan menambahkan kode berikut.

type loginAuth struct {
    username, password string
}

func LoginAuth(username, password string) smtp.Auth {
    return &loginAuth{username, password}
}

func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
    // return "LOGIN", []byte{}, nil
    return "LOGIN", []byte(a.username), nil
}

func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
    if more {
        switch string(fromServer) {
        case "Username:":
            return []byte(a.username), nil
        case "Password:":
            return []byte(a.password), nil
        }
    }
    return nil, nil
}

Ubah metode pemanggilan sebagai berikut:

auth := LoginAuth(user, password)

Gunakan Port 465

package main

import (
    "crypto/tls"
    "fmt"
    "log"
    "net"
    "net/smtp"
)

func main() {
    host := "smtpdm.aliyun.com"
    port := 465
    email := "test***@example.net"
    password := "TExxxxxst"
    toEmail := "test1***@example.net"

    header := make(map[string]string)
    header["From"] = "test" + "<" + email + ">"
    header["To"] = toEmail
    header["Subject"] = "Email Title"
    header["Content-Type"] = "text/html; charset=UTF-8"

    body := "This is a test email!"
    message := ""
    for k, v := range header {
        message += fmt.Sprintf("%s: %s\r\n", k, v)
    }
    message += "\r\n" + body

    auth := smtp.PlainAuth(
        "",
        email,
        password,
        host,
    )

    err := SendMailUsingTLS(
        fmt.Sprintf("%s:%d", host, port),
        auth,
        email,
        []string{toEmail},
        []byte(message),
    )

    if err != nil {
        panic(err)
    } else {
        fmt.Println("Send mail success!")
    }
}

//return a smtp client
func Dial(addr string) (*smtp.Client, error) {
    conn, err := tls.Dial("tcp", addr, nil)
    if err != nil {
        log.Println("Dialing Error:", err)
        return nil, err
    }
    // Split the host and port from the string.
    host, _, _ := net.SplitHostPort(addr)
    return smtp.NewClient(conn, host)
}

// See the SendMail() function in net/smtp.
// When you use net.Dial to connect to a TLS (SSL) port, smtp.NewClient() may hang without returning an error.
// If len(to) is greater than 1, recipients from to[1] onwards are treated as BCC recipients.
func SendMailUsingTLS(addr string, auth smtp.Auth, from string,
    to []string, msg []byte) (err error) {

    //create smtp client
    c, err := Dial(addr)
    if err != nil {
        log.Println("Create smpt client error:", err)
        return err
    }
    defer c.Close()

    if auth != nil {
        if ok, _ := c.Extension("AUTH"); ok {
            if err = c.Auth(auth); err != nil {
                log.Println("Error during AUTH", err)
                return err
            }
        }
    }

    if err = c.Mail(from); err != nil {
        return err
    }

    for _, addr := range to {
        if err = c.Rcpt(addr); err != nil {
            return err
        }
    }

    w, err := c.Data()
    if err != nil {
        return err
    }

    _, err = w.Write(msg)
    if err != nil {
        return err
    }

    err = w.Close()
    if err != nil {
        return err
    }

    return c.Quit()
}