エラー通知またお知らせを送信するために、メール自動送信機能を持つアプリが多いです。Python/Rust/Go/JavascriptでGmailを自動的に送信する機能を開発する手順をメモします。
メールを送信うする際、通信規定のSMTP(Simple Mail Transfer Protocol)があります。SMTPで使用されるデフォルトポートは587番ポートです。本記事でSMTPを設定する場合、587番ポートを使います。
Gmailアプリパスワードを設定
最初に、Google アカウントを開いて、2段階認証をオンにします。次に、2段階認証でアプリパスワードを設定します。アプリパスワードは登録のパスワードではないです。メールを自動送信する際、アプリパスワードを使います。
アプリパスワードを設定した後、.envに送信メール、受信メールとアプリパスワードを保存します。
SENDER=sender@gmail.com
PASSWORD=apppassword
RECEIVER=receiver@gmail.com
Javascriptで作成
ここでnodemailerライブラリを使用します。非同期処理async...awaitを使います。
smtpを設定する際、nodemailer.createTransport()を使ってSMTPトランスポートを作ります。Gmailを送信しますので、host="smtp.gmail.com"とhost=587にします。
// Reference: https://nodemailer.com/about/
"use strict";
const nodemailer = require("nodemailer");
//環境変数を取得
const dotenv = require('dotenv')
dotenv.config()
let mail_content = "Hello,This is a simple mail. There is only text, no attachments are there. The mail is sent using Js NodeEmail.Thank You!!!"
// async..await is not allowed in global scope, must use a wrapper
async function send_email(content) {
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: process.env.SENDER, // user
pass: process.env.PASSWORD, // password
},
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: process.env.SENDER, // sender address
to: process.env.RECEIVER, // list of receivers
subject: "Test", // Subject line
text: content, // plain text body
});
}
send_email(mail_content).catch(console.error);
Pythonで作成
Pythonにsmtplib(SMTPのライブラリ)が提供されています。メールをMIME形式に返還しなければなりません。
メッセージをMIME形式に変換する際、MIMEMultipart()でMIMEオブジェクトを作ります。
SMTPサーバを設定する際、smtplib.SMTPを使います。
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os
from decouple import config
# Reference: https://www.tutorialspoint.com/send-mail-from-your-gmail-account-using-python
mail_content = '''
Hello,
This is a simple mail. There is only text, no attachments are there. The mail is sent using Python SMTP library.
Thank You!!!
'''
#The mail addresses and password
sender_addrs = config('SENDER')
sender_pass = config("PASSWORD")
receiver_addrs = config('RECEIVER')
#Setup the MIME
def set_message(sender_addrs, sender_pass, receiver_addrs, mail_content):
message = MIMEMultipart()
message['From'] = sender_addrs
message['To'] = receiver_addrs
message['Subject'] = 'A test mail sent by Python. It has an attachment.' #The subject line
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
return message
#Create SMTP session for sending the mail
def send_email_smtp(sender_addrs, receiver_addrs, message):
session = smtplib.SMTP('smtp.gmail.com', 587) #use gmail with port
session.starttls() #enable security
session.login(sender_addrs, sender_pass) #login with mail_id and password
text = message.as_string()
session.sendmail(sender_addrs, receiver_addrs, text)
session.quit()
print('Mail Sent')
if __name__=="__main__":
# MIME形式に変換
message = set_message(sender_addrs, sender_pass, receiver_addrs, mail_content)
# メール送信
send_email_smtp(sender_addrs, receiver_addrs, message)
Goで作成
Golangに"net/smtp"を使う方法と"gomail"を使う方法があります。
"net/smtp"を使う際、smtp.PlainAuthでAuthオブジェクトを作ります。次にsmtp.SendMailメソッドでメッセージを送信します。
"gomail"を使う際、gomail.NewMessageでメッセージオブジェクトを使います。メール送信メール、受信メールとコンテンツをメッセージオブジェクトで設定します。SMTPサーバを設定する際、gomail.NewDialerを使います。
// Reference: https://www.loginradius.com/blog/engineering/sending-emails-with-golang/
package main
import (
"fmt"
"net/smtp"
"os"
"github.com/joho/godotenv"
"log"
"crypto/tls"
gomail "gopkg.in/mail.v2"
)
func main() {
godotenv_err := godotenv.Load()
if godotenv_err != nil {
log.Fatal("Error loading .env file")
}
// Sender data.
sender := os.Getenv("SENDER")
password := os.Getenv("PASSWORD")
// Receiver email address.
receiver := []string{
os.Getenv("RECEIVER"),
}
// Message.
message := []byte("Hello,This is a simple mail. There is only text, no attachments are there. The mail is sent using Golang. Thank You!!!")
// send_email_smtp(sender, password, receiver, message)
send_email_gomail(sender, password, receiver, message)
}
func send_email_smtp(sender string, password string, receiver []string, message []byte) {
// smtp server configuration.
smtpHost := "smtp.gmail.com"
smtpPort := "587"
// Authentication.
auth := smtp.PlainAuth("", sender, password, smtpHost)
// Sending email.
err := smtp.SendMail(smtpHost+":"+smtpPort, auth, sender, receiver, message)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Email Sent Successfully!")
}
func send_email_gomail(sender string, password string, receiver []string, message []byte) {
mail := gomail.NewMessage()
// Set E-Mail sender
mail.SetHeader("From", sender)
// Set E-Mail receivers
mail.SetHeader("To", receiver[0])
// Set E-Mail subject
mail.SetHeader("Subject", "Gomail test subject")
// Set E-Mail body. You can set plain text or html with text/html
mail.SetBody("text/plain", string(message[:]))
// Settings for SMTP server
server := gomail.NewDialer("smtp.gmail.com", 587, sender, password)
// This is only needed when SSL/TLS certificate is not valid on server.
// In production this should be set to false.
server.TLSConfig = &tls.Config{InsecureSkipVerify: true}
// Now send E-Mail
if err := server.DialAndSend(mail); err != nil {
fmt.Println(err)
panic(err)
}
}
Rustで作成
mail_sendとmail_builderライブラリを使います。Javascriptと同じで、非同期処理を使います。
まず、mail_builder::MessageBuilderでメッセージオブジェクトを作ります。このオブジェクトは送信メール、受信メールとメールコンテンツの情報を持ちます。
mail_send::SmtpClientBuilderを使い、SMTPクライアントを作ります。次に、パスワードを使ってcredentialsを設定します。最後にメールを送信します。
use dotenv;
use std::env;
use mail_builder::MessageBuilder;
use mail_send::SmtpClientBuilder;
#[tokio::main]
async fn main() {
dotenv::dotenv().ok();
let sender = match env::var("SENDER"){
Ok(val) => val,
Err(e) => panic!("could not find {}: {}", "SENDER", e),
} ;
let password = match env::var("PASSWORD"){
Ok(val) => val,
Err(e) => panic!("could not find {}: {}", "PASSWORD", e),
};
let receiver = match env::var("RECEIVER") {
Ok(val) => val,
Err(e) => panic!("could not find {}: {}", "RECEIVER", e),
};
let content = "Hello,This is a simple mail. There is only text, no attachments are there. The mail is sent using Rust. Thank You!!!";
send_email_smtp(&sender, &password, &receiver, content).await;
}
async fn send_email_smtp(sender:&str, password:&str, receiver:&str, content:&str) {
// Build a simple multipart message
let message = MessageBuilder::new()
.from(("", sender))
.to(vec![
("", receiver),
])
.subject("Test!")
.text_body(content);
// Connect to the SMTP submissions port, upgrade to TLS and
// authenticate using the provided credentials.
SmtpClientBuilder::new("smtp.gmail.com", 587)
.implicit_tls(false)
.credentials((sender, password))
.connect()
.await
.unwrap()
.send(message)
.await
.unwrap();
}
参考
[1] https://nodemailer.com/about/
[2] https://www.tutorialspoint.com/send-mail-from-your-gmail-account-using-python
[3] https://www.loginradius.com/blog/engineering/sending-emails-with-golang/
[4] https://docs.rs/mail-send/latest/mail_send/