ポート 80 の使用
Go 言語を使用して SMTP 経由でメールを送信できます。このコードは Go バージョン 1.16.5 で検証されています。
説明
ポート 465 で TLS 暗号化を使用するには、以下のセクションをご参照ください。この目的でポート 80 のコードを使用しないでください。
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 := "コンソールで作成された送信元アドレス"
password := "コンソールで設定された SMTP パスワード"
host := "smtpdm.aliyun.com:80"
to := []string{"受信者アドレス","受信者アドレス_1"}
cc := []string{"cc_アドレス","cc_アドレス_1"}
bcc := []string{"bcc_アドレス","bcc_アドレス_1"}
subject := "Golang でのメール送信テスト"
date := fmt.Sprintf("%s", time.Now().Format(time.RFC1123Z))
mailtype :="html"
replyToAddress:="a***@example.net"
body := "<html><body><h3>メール送信テスト</h3></body></html>"
fmt.Println("メールを送信")
err := SendToMail(user, password, host, subject,date, body, mailtype, replyToAddress, to, cc, bcc)
if err != nil {
fmt.Println("メールの送信エラー!")
fmt.Println(err)
} else {
fmt.Println("メールの送信に成功しました!")
}
}
func MergeSlice(s1 []string, s2 []string) []string {
slice := make([]string, len(s1)+len(s2))
copy(slice, s1)
copy(slice[len(s1):], s2)
return slice
}説明
Go バージョン 1.9.2 を使用する場合、このバージョンでは暗号化された認証が必要なため、「unencrypted connection」エラーが発生することがあります。この問題を解決するには、次のコードを追加して LOGIN 認証を使用します。
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
}呼び出しメソッドを次のように変更します:
auth := LoginAuth(user, password)ポート 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"] = "メールの件名"
header["Content-Type"] = "text/html; charset=UTF-8"
body := "これはテストメールです!"
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("メールの送信に成功しました!")
}
}
// smtp クライアントを返します
func Dial(addr string) (*smtp.Client, error) {
conn, err := tls.Dial("tcp", addr, nil)
if err != nil {
log.Println("ダイヤルエラー:", err)
return nil, err
}
// 文字列からホストとポートを分割します。
host, _, _ := net.SplitHostPort(addr)
return smtp.NewClient(conn, host)
}
// net/smtp の SendMail() 関数をご参照ください。
// net.Dial を使用して TLS (SSL) ポートに接続すると、smtp.NewClient() がエラーを返さずにハングすることがあります。
// len(to) が 1 より大きい場合、to[1] 以降の受信者は BCC 受信者として扱われます。
func SendMailUsingTLS(addr string, auth smtp.Auth, from string,
to []string, msg []byte) (err error) {
// smtp クライアントを作成します
c, err := Dial(addr)
if err != nil {
log.Println("smpt クライアントの作成エラー:", err)
return err
}
defer c.Close()
if auth != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(auth); err != nil {
log.Println("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()
}