Python
mail
sendmail
smtplib

Pythonでカンマ区切りで複数送信先にメール送信しようとしたら先頭にしか送信されなかった話

前提:2系(2.7)

Pythonで作ったバッチ処理の通知用にメール送信処理を作ってみたら、思った送信先に送信されなかったという話。

やったこと

smtplibのsendmail関数を使って、以下の要領で複数の送信先に対してメール送信しようとしていた。

cset = 'utf-8'
msg = MIMEMultipart()
msg["Subject"] = subject
msg["From"] = from_addr_name+"<"+from_addr+">"
msg["To"] = to_addr # 複数送信先の場合は,区切りで入力されていることを期待
msg["Cc"] = cc_addr # 複数送信先の場合は,区切りで入力されていることを期待
msg["Date"] = formatdate()
body = MIMEText(body.encode("utf-8"), 'plain', 'utf-8')
msg.attach(body)

# 送信処理
smtp = smtplib.SMTP(smtp_server)
smtp.ehlo()
smtp.starttls()
smtp.ehlo
smtp.login(login_id, login_password)
smtp.sendmail(from_addr, to_addr+cc_addr, msg.as_string())
smtp.close()

間違ってた

上記だととりあえずメールは送信されるのだが、Toの先頭にしかメールが送信されていなかった。

テスト/調査の感じだと、msg["To"] やmsg["Cc"]に設定したものはメール文面の表示にしか使用されていない模様。

で、実際の送信先についてはsendmail()の第二引数にリストで渡すことで複数送信先に送信できるようになっている模様。

つまり

sendToList=to_addr.split(',')+cc_addr.split(',')
smtp.sendmail(from_addr, sendToList, msg.as_string())

のようにしてあげる必要があった。

msgはカンマ区切りでもいいけど、sendmailはリストじゃないとダメってめんどくさい仕様だな。

※ちなみに後から考えると

仮にカンマ区切りで複数に送信できるとしても

smtp.sendmail(from_addr, to_addr+cc_addr, msg.as_string())

だとToの最後とCcの先頭がカンマで区切られていないのでどちらにしてもダメだったような気がする。

参考

公式:smtplib

サンプル

ConfigParserを使ってsetting.iniファイルから設定情報を取得。

ファイルの添付などは無し。

# -*- coding: utf-8 -*-

import smtplib
from email.Utils import formatdate
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText    

class SendMail(object):

   # メールの作成
   @staticmethod
   def SendMessage(subject, body):

   import ConfigParser
   inifile = ConfigParser.SafeConfigParser()
   inifile.read('./setting.ini')

   # 設定ファイル内でメール送信実施の制御を行えるようにしている。
   if inifile.get('Debug', 'SendFlg') == "False":
   print("[Debug Mode] No Send Mail")
   return

   from_addr=inifile.get('Address', 'fromAddress')
   from_addr_name = inifile.get('Address', 'fromAddressName')
   to_addr = inifile.get('Address', 'toAddress')  # 複数送信先の場合は,区切りで入力されていることを期待
   cc_addr = inifile.get('Address', 'ccAddress')  # 複数送信先の場合は,区切りで入力されていることを期待
   # SMTP
   smtp_server = inifile.get('Address', 'SMTP_SERVER')
   login_id = inifile.get('Address', 'fromAddress') # 送信元アドレスでログインすることになる
   login_password = inifile.get('Address', 'SMTP_Pass')

   cset = 'utf-8'
   msg = MIMEMultipart()
   msg["Subject"] = subject
   msg["From"] = from_addr_name+"<"+from_addr+">"
   msg["To"] = to_addr
   msg["Cc"] = cc_addr
   msg["Date"] = formatdate()
   body = MIMEText(body.encode("utf-8"), 'plain', 'utf-8')
   msg.attach(body)


   # 送信処理
   smtp = smtplib.SMTP(smtp_server)
   smtp.ehlo()
   smtp.starttls()
   smtp.ehlo
   smtp.login(login_id, login_password)
   sendToList=to_addr.split(',')+cc_addr.split(',')
   smtp.sendmail(from_addr, sendToList, msg.as_string())
   smtp.close()
   # smtp.quit()

添付ファイルも送りたかったら、msgにattachしてあげれば送れるはず。

追記

上記のサンプルを別の環境にもっていって、使ってみたら動かなくていくつか調整が必要だった。
まず、

  • ログイン等が不要なSMTPサーバだった。
  • SMTPサーバからのレスポンスがないコマンドがあった

ということで、いくつかの部分を適当にコメントアウトして使える状態にした。