CDO(Microsoft Collaboration Data Objects)を使ったメールの一括送信Excelマクロが、転送エラーを返すようになった、とのこと。
メールの送信には Microsoft365 を使っています。
結局、解決には至りませんでしたが、誰かの役に立てればと調べた結果を共有します。
追記
解決しました。Exchangeオンラインで設定変更後、特定の環境からポート25で接続に成功しました。
やったこと
PowerShellからExchangeオンラインに接続します。
Connect-ExchangeOnline -UserPrincipalName foo@example.com -ShowProgress $true
この後、パスワードやワンタイムパスコードを入力します。
Get-InstalledModule
の結果にExchangeOnlineManagement
が無ければ、事前にモジュールを有効化しましょう。
Install-Module -Name ExchangeOnlineManagement -Force
Import-Module ExchangeOnlineManagement
設定を確認します。
Get-CASMailbox -Identity bar@example.com
制限されていれば解除します。
Set-CASMailbox -Identity bar@example.com -ImapEnabled $true -PopEnabled $true -MapiEnabled $true -ActiveSyncEnabled $true
SMTP AUTH も有効にしておきます。
Set-CASMailbox -Identity bar@example.com -SmtpClientAuthenticationDisabled $false
なお、$null を指定するとテナントのグローバル設定に従います。
テナントのグローバル設定を確認するには、
Get-TransportConfig | Format-List SmtpClientAuthenticationDisabled
グローバルIPアドレスによる接続制限をかけられていないかも確認しておきます。
何も表示されなければ個別の定義はありません。
Get-ClientAccessRule
これらの設定確認および変更は、Exchange管理センターからも一部できるようになりました。
テナントで基本認証がブロックされていないことも確認しておきます。
Microsoft管理センター [設定]-[組織設定] から先進認証をクリックします。
なお、先進認証(Modern Authentication:モダン認証とかADAL認証とも呼ばれます)とは、HTTPSでアクセストークン(アクセス許可、権限範囲、有効期限が示されたチケットのようなもの)をサーバに送信する方式のことです。これに対し、基本認証(Basic authentication:ベーシック認証とかレガシー認証とも呼ばれます)は、ユーザ名とパスワードをサーバに送信します。
しかし・・・
状況は改善されません。
CDOで指示するポート番号を 25、465(SSL/SMTPS)、587(TLS/STARTTLS 要SMTP AUTH)と変えてみてもダメでした。
外部のサーバからtelnet
で直接接続を試みます。
$ telnet smtp.office365.com 25
Trying xxx.xxx.xxx.xxx...
Trying yyy.yyy.yyy.yyy...
:
telnet: Unable to connect to remote host: Connection timed out
できませんでした。認証/認可の前に繋がらないのはおかしいです。
Connection refused
(接続拒否)が返ってこないので、サーバでポートがリッスンしていないわけでは無いことが判ります。
このときにパケットをキャプチャしてみると、SYNパケットを繰り返し送信するだけで、相手から何の応答もありません。これはどこかでパケットを遮断していると判ります。(サーバが拒否しているならSYNに対してRSTを応答するはず)
# tcpdump port 25
07:53:50.271175 IP6 XXXXX > YYYYY.smtp: Flags [S], seq 2530573894, win 62587, options [mss 8941,sackOK,TS val 1414108762 ecr 0,nop,wscale 6], length 0
07:53:50.271175 IP6 XXXXX > YYYYY.smtp: Flags [S], seq 2530573894, win 62587, options [mss 8941,sackOK,TS val 1414108762 ecr 0,nop,wscale 6], length 0
:
経路をみてみます。相手方のネットワークまでは到達しているようです。
# mtr smtp.office365.com -P 25
My traceroute [v0.92]
example.com (xxx.xxx.xxx.xxx) 2022-11-02T22:33:22+0900
Keys: Help Display mode Restart statistics Order of fields quit
Packets Pings
Host Loss% Snt Last Avg Best Wrst StDev
1. ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com 0.0% 14 5.0 14.1 1.0 76.4 24.1
:
:
22. zzzzz.icr02.tyo30.ntwk.msn.net 0.0% 13 4.1 4.4 3.6 7.6 1.1
:
:
28. 40.99.36.zzz 0.0% 13 2.9 2.9 2.9 3.0 0.0
TLS/SSL接続ではどうでしょう。openssl
で試してみます。
SMTP AUTH ではユーザー名とパスワードをbase64でエンコードした文字列を渡すことになるので予め求めておきましょう。
$ printf 'user@example.com' | base64
$ printf 'password' | base64
smtp.office365.com では-crlf
を付けないとうまくいきませんでした。
$ openssl s_client -connect smtp.office365.com:587 -quiet -crlf -starttls smtp
サーバとのやり取りを示します。
4文字の英字で始まる行はクライアントから入力したSMTPのコマンド、3桁の数字で始まる行はサーバからの応答です。
AUTHコマンドの後に続くXXXXXXがbase64エンコードしたユーザー名、YYYYYYがbase64エンコードしたパスワードになります。
HELOコマンドではなく拡張されたEHLOコマンドを使うことで、SMTPサーバがどんな認証方法に対応しているか知ることができます。
EHLO localhost
250-TYWPR01CA0023.outlook.office365.com Hello [xxx.xxx.xxx.xxx]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH LOGIN XOAUTH2
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
AUTH LOGIN
334 VXNlcm5hbWU6
XXXXXX
334 UGFzc3dvcmQ6
YYYYYY
235 2.7.0 Authentication successful
MAIL FROM: foo@example.com
250 2.1.0 Sender OK
RCPT TO: bar@example.co.jp
250 2.1.5 Recipient OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
From: foo@example.com
Subject: TEST
Hello world
.
250 2.0.0 OK <zzzzzzzz.jpnprd01.prod.outlook.com> [Hostname=zzzzzzzz.jpnprd01.prod.outlook.com]
QUIT
221 2.0.0 Service closing transmission channel
接続に成功し、認証方式は SMTP AUTH LOGIN と XOAUTH2 に対応していることが判ります。
さらに調べていくと、海外のブログにヒントが。
昨年末あたりからTLS接続が必須になり、従来のSSL接続をサーバが拒否するようになった、と書かれています。
その一方で、CDOにSSL接続を指示すると実際にはSSLの後継であるTLSが裏で動いている、というコメントも寄せられています。
テナントによって挙動が違うのは、10月1日以降、Microsoftがテナントをランダムに選択して、基本認証(ここではSMTP AUTH以外のこと)のアクセスを無効にしたことも関係しているのでしょうか。こちらのコミュニティにはそのようなことが書かれています。
VPNで社内環境に接続したら送信できた、という事例も見つけました。(グローバルIPアドレスをチェックしている?)
追記
最終的にはこの情報が解決の糸口になりました。
これまでは自宅で調査していたのですが、社内から接続したところ、あっさりと成功しました。
結論
Microsoftは今後、Exchangeオンラインの SMTP AUTH も無効にする(OAuthベースの先進認証に移行していく)と考えられるので、CDOを使った方法はもう諦めた方が良さそうです。
先述と同じ人のブログですが、ノーコードツールの Power Automate でGoogleスプレッドシートと連携し、Microsoft365メールを一括で送信していました。これは素晴らしいですね!
参考ドキュメント