2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python/Rust/Go/JavascriptでGmailを自動送信

Last updated at Posted at 2023-05-16

エラー通知またお知らせを送信するために、メール自動送信機能を持つアプリが多いです。Python/Rust/Go/JavascriptでGmailを自動的に送信する機能を開発する手順をメモします。

メールを送信うする際、通信規定のSMTP(Simple Mail Transfer Protocol)があります。SMTPで使用されるデフォルトポートは587番ポートです。本記事でSMTPを設定する場合、587番ポートを使います。

Screen Shot 2023-05-15 at 22.20.25.png

Gmailアプリパスワードを設定

最初に、Google アカウントを開いて、2段階認証をオンにします。次に、2段階認証でアプリパスワードを設定します。アプリパスワードは登録のパスワードではないです。メールを自動送信する際、アプリパスワードを使います。

Screen Shot 2023-05-15 at 21.45.22.png

Screen Shot 2023-05-15 at 21.45.37.png

アプリパスワードを設定した後、.envに送信メール、受信メールとアプリパスワードを保存します。

.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/

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?