Todos os produtos
Search
Central de documentação

Direct Mail:Como chamar SMTP com Go: código de exemplo

Última atualização: Jun 27, 2026

Envie e-mails de uma aplicação Go usando o serviço SMTP do Direct Mail. Dois exemplos completos abrangem a porta 80 (conexão simples com autenticação PLAIN ou LOGIN) e a porta 465 (tls implícito).

O Direct Mail oferece dois endpoints SMTP. Use a porta 80 para conexão simples com autenticação PLAIN ou LOGIN. Para tls implícito, em que o handshake tls ocorre antes de qualquer comando SMTP, use a porta 465. Ambos os exemplos foram validados no Go 1.16.5 e usam smtpdm.aliyun.com como host SMTP.

Pré-requisitos

Antes de começar, verifique se você tem:

  • Um endereço de remetente verificado configurado no console do Direct Mail

  • A senha SMTP desse endereço de remetente

Uso da porta 80

O exemplo abaixo envia um e-mail HTML com destinatários nos campos To, CC e BCC. A função MergeSlice combina as três listas de destinatários em uma única lista de envelope SMTP. Isso é necessário porque o comando RCPT TO do SMTP defina quais caixas de correio recebem a mensagem, independentemente dos cabeçalhos do e-mail.

Substitua as strings de espaço reservado na função main() pelo seu endereço de remetente e pela senha SMTP obtidos no console do Direct Mail.

Nota

Para enviar por uma conexão criptografada, use o exemplo da porta 465 abaixo. Não use o código da porta 80 para conexões tls.

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
}

Nota de compatibilidade com Go 1.9.2

Nota

O Go 1.9.2 exige autenticação criptografada e rejeita uma chamada simples a PlainAuth com o erro "unencrypted connection". Para resolver, substitua a chamada a smtp.PlainAuth pela implementação personalizada de LoginAuth abaixo.

Adicione a seguinte implementação de LoginAuth ao seu arquivo:

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
}

Em seguida, substitua a linha de autenticação em main() por:

auth := LoginAuth(user, password)

Uso da porta 465

A porta 465 usa tls implícito: o handshake tls ocorre antes de qualquer comando SMTP. Por isso, não é possível usar diretamente a função nativa SendMail do pacote net/smtp. Este exemplo defina uma função personalizada Dial que abre uma conexão tls via tls.Dial e uma função SendMailUsingTLS que gerencia a sessão SMTP manualmente.

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!")
    }
}

// Dial opens an implicit TLS connection and returns an 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 address string.
    host, _, _ := net.SplitHostPort(addr)
    return smtp.NewClient(conn, host)
}

// SendMailUsingTLS sends an email over an implicit TLS connection.
// 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 the 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()
}