Groovyでメール送信用クラス作成

2019-01-23Groovy, Java

Javaではよく知られる、JavaMailを使ったメール送信のためのクラスをGroovyで作成してみる。

通常は1つのSMTPサーバーしか使用しないと思うので、 このクラスの設定項目を変更して配置すれば、 システム内でのメール送信はカバーできると思います。


※注意! (2019-01-23)

久しぶりにこちらのコードを実行してみたところ、以下のようなエラーが発生しました。
Googleのセキュリティが厳しくなったためにログインできなくなっているように見えます。
XOAUTH2 という文言が見えるので、 OAUTH2 による認証が必要なようですね。
( トークンを取得して一緒に送信しないといけない?? )

ご存知の方がいらっしゃいましたら @genzouw まで連絡ください。

DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL false
220 smtp.gmail.com ESMTP 202sm21577506pfy.87 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 465

EHLO 192.168.25.251
250-smtp.gmail.com at your service, [221.250.87.66]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: STARTTLS requested but already using SSL
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN failed
javax.mail.AuthenticationFailedException: 534-5.7.9 Application-specific password required. Learn more at
534 5.7.9  https://support.google.com/mail/?p=InvalidSecondFactor 202sm21577506pfy.87 - gsmtp

        at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:826)
        at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:761)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:685)
        at javax.mail.Service.connect(Service.java:317)
        at javax.mail.Service.connect(Service.java:176)
        at javax.mail.Service.connect(Service.java:125)
        at javax.mail.Transport.send0(Transport.java:194)
        at javax.mail.Transport.send(Transport.java:124)
        at javax.mail.Transport$send.call(Unknown Source)

必要なライブラリ

Groovyソースコード

  • GenzouwServerMail.groovy としてファイルを作成します。
  • 必要ならライブラリは Grab 機能を使って、実行時に自動的にダウンロードします。
@Grapes(
    @Grab(group='javax.mail', module='mail', version='1.4.7')
)

import java.util.Properties

import java.io.*
import javax.mail.*
import javax.mail.internet.*
import javax.activation.*

class GenzouwServerMail {
    def charset="UTF-8"

    def smtpUser = "※ここに送信者メールアドレスを記入※"

    def smtpHost = "※ここにサーバー名/IPを記入※"

    def smtpPassword = "※ここにパスワードを記入※"

    def fromAddress = "※ここにメールアドレスを記入※"

    def senderName = "※ここに送信者名を記入※"

    def send(toAddress, subject, text, filepath = null) {

        Properties p = new Properties()
        p.put("mail.smtp.user", smtpUser)
        p.put("mail.smtp.host", smtpHost)
        p.put("mail.smtp.port", "465")
        p.put("mail.smtp.starttls.enable", "true")
        p.put("mail.smtp.auth", "true")
        p.put("mail.smtp.debug", "true")
        p.put("mail.smtp.socketFactory.port", "465")
        p.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory")
        p.put("mail.smtp.socketFactory.fallback", "false")

        SecurityManager security = System.getSecurityManager()

        try {
            Authenticator auth = new javax.mail.Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(smtpUser, smtpPassword)
                }
            }
            Session session = Session.getInstance(p, auth)
            session.debug = true

            def msg = new MimeMessage(session)
            msg.text = text
            msg.subject = subject
            msg.from = new InternetAddress(fromAddress, senderName)
            msg.setHeader("Content-Type", "text/plain charset=" + charset)
            msg.addRecipient(
                Message.RecipientType.TO,
                new InternetAddress(toAddress)
            )

            if (filepath != null) {
                def mbp = new MimeBodyPart()
                def fds = new FileDataSource(filepath)
                mbp.dataHandler = new DataHandler(fds)
                mbp.fileName = MimeUtility.encodeWord(fds.getName())
                // 複数のボディを格納するマルチパートオブジェクトを生成
                def mp = new MimeMultipart()
                mp.addBodyPart(mbp)
                // マルチパートオブジェクトをメッセージに設定
                msg.content = mp
            }

            Transport.send(msg)
        } catch (Exception mex) {
            mex.printStackTrace()
        }
    }
}

使い方

利用先のGroovyスクリプトは以下のような感じ。

sample.groovy

mail = new GenzouwServerMail()

mail.smtpUser = "genzouw@gmail.com"
mail.smtpHost = "smtp.gmail.com"
mail.smtpPassword = "XXXXXX"
mail.fromAddress = "genzouw@gmail.com"
mail.senderName = "genzouw"

mail.send("test@gmail.com", "テスト", "とどくかな")

実行例

# 同じディレクトリにスクリプトを2つ配置
$ ls *.groovy
GenzouwServerMail.groovy sample.groovy

$ groovy -cp . sample.groovy

2019-01-23Groovy, Java