golang 使用Go发送电子邮件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 使用Go发送电子邮件相关的知识,希望对你有一定的参考价值。

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/smtp"
	"strings"
)

//Mailer contains info on email sender and receiver
type Mailer struct {
	SenderEmail    string   `json:"senderEmail"`
	Password       string   `json:"password"`
	SMTPServerHost string   `json:"smtpServerHost"`
	SMTPServerPort int      `json:"smtpServerPort"`
	ReceiverEmails []string `json:"receiverEmails"`
}

// NewMailer inits a new mailer based on configuration
func NewMailer(in io.Reader) (mail *Mailer, err error) {
	decoder := json.NewDecoder(in)
	mail = new(Mailer)
	err = decoder.Decode(mail)
	if err != nil {
		log.Println(err)
		return
	}
	return
}

func validateMailConfig(mailer Mailer) error {
	if mailer.SMTPServerHost == "" || mailer.SMTPServerPort == 0 {
		return fmt.Errorf("Error: no SMTP server or port configured")
	}
	if len(mailer.ReceiverEmails) < 1 {
		return fmt.Errorf("Error: No mail receiver is specified")
	}
	if !strings.Contains(mailer.SenderEmail, "@") {
		return fmt.Errorf("Error: invalid email sender: %s", mailer.SenderEmail)
	}
	return nil

}

func composeBody(subject, body, name, from string) []byte {
	buf := bytes.NewBuffer(nil)
	buf.WriteString("Subject: " + subject + "\r\n")
	buf.WriteString("MIME-Version: 1.0\r\n")
	buf.WriteString(fmt.Sprintf("From: %s <%s>\r\n", name, from))
	buf.WriteString(fmt.Sprintf("Content-Type: text/html; charset=utf-8\r\n\r\n"))
	buf.WriteString(body)
	return buf.Bytes()
}

//SendEmail sends the mail with subject and body set
func (mailer Mailer) SendEmail(subject, senderName, body string) (err error) {
	err = validateMailConfig(mailer)
	if err != nil {
		return
	}
	auth := smtp.PlainAuth(
		"",
		mailer.SenderEmail,
		mailer.Password,
		mailer.SMTPServerHost)
	conn, err := smtp.Dial(fmt.Sprintf("%s:%d", mailer.SMTPServerHost, mailer.SMTPServerPort))
	if err != nil {
		return
	}
	err = conn.StartTLS(&tls.Config{ServerName: mailer.SMTPServerHost})
	if err != nil {
		return
	}
	err = conn.Auth(auth)
	if err != nil {
		return
	}
	err = conn.Mail(mailer.SenderEmail)
	if err != nil {
		if strings.Contains(err.Error(), "530 5.5.1") {
			err = fmt.Errorf("Error: Authentication failure. ")

		}
		return
	}
	for _, recv := range mailer.ReceiverEmails {
		err = conn.Rcpt(recv)
		if err != nil {
			return
		}
	}

	wc, err := conn.Data()
	if err != nil {
		return
	}
	defer wc.Close()
	bodybytes := composeBody(subject, body, senderName, mailer.SenderEmail)
	_, err = wc.Write(bodybytes)
	if err != nil {
		return
	}
	return nil
}

在 golang 中使用 gmail API 发送带附件的电子邮件

【中文标题】在 golang 中使用 gmail API 发送带附件的电子邮件【英文标题】:send email with attachment using gmail API in golang 【发布时间】:2016-09-28 04:16:56 【问题描述】:

我已关注https://developers.google.com/gmail/api/quickstart/go。我将范围修改为 gmail.MailGoogleComScope 并尝试发送电子邮件。电子邮件被发送。但是,没有发送附件。它也没有给出任何错误。请注意,对 Media 函数的调用是我尝试查看 gmail API 中的代码,但不确定这是否正确。

当我将 contentType 设置为 application/png 时,API 会抛出异常消息“不支持 png,请使用 message/rfc822”。以下是 SendEmail 的代码。

func SendEmail(msg EmailMessage) 
  ctx := context.Background()

  b, err := ioutil.ReadFile("/tmp/client_secret.json")
  if err != nil 
    log.Fatalf("Unable to read client secret file: %v", err)
  

  config, err := google.ConfigFromJSON(b, gmail.MailGoogleComScope)
  if err != nil 
    log.Fatalf("Unable to parse client secret file to config: %v", err)
  
  client := getClient(ctx, config)

  srv, err := gmail.New(client)
  if err != nil 
    log.Fatalf("Unable to retrieve gmail Client %v", err)
  

  var message gmail.Message
  temp := []byte("From: 'me'\r\n" +
    "reply-to: sender@gmail.com\r\n" +
    "To:  " + msg.To + "\r\n" +
    "Subject: " + msg.Subject + "\r\n" +
    "\r\n" + msg.Body)

  message.Raw = base64.StdEncoding.EncodeToString(temp)
  message.Raw = strings.Replace(message.Raw, "/", "_", -1)
  message.Raw = strings.Replace(message.Raw, "+", "-", -1)
  message.Raw = strings.Replace(message.Raw, "=", "", -1)

  imgFile, err := os.Open("image.png") // a QR code image

  if err != nil 
    log.Fatalf("Error in opening file")
  
  defer imgFile.Close()

  mediaOptions := googleapi.ContentType("message/rfc822")
  _, err = srv.Users.Messages.Send("me", &message).Media(imgFile,  mediaOptions).Do()
  if err != nil 
    log.Fatalf("Unable to send. %v", err)
  

请指出缺少的内容

【问题讨论】:

您应该尝试在不使用Media() 方法的情况下在message.Raw 内发送整个消息(包括附件,带有适当的标头)。我已经取得了一些成功,但没有使用正确的标题,所以我不会发布任何工作代码。 【参考方案1】:

我也遇到了同样的问题,看了很久才找到支持附件的库https://github.com/jordan-wright/email

【讨论】:

我知道我需要标记为重复但还没有声誉 有没有办法使用访问令牌? github.com/jordan-wright/email 方法需要用户的密码

以上是关于golang 使用Go发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

在 golang 中使用 gmail API 发送带附件的电子邮件

GoLang邮件发送Demo(继上篇msmtp)

在 Golang 中附加文件并通过 SMTP 发送时没有正文部分的电子邮件

Go语言入门150题 L1-053 电子汪 (10 分) Go语言|Golang

golang 在Go lang发送并获取Json

golang 使用 gomail 发送邮件