1
2

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.

CDOでMicrosoft365メールが使えなくなったので調べてみた

Last updated at Posted at 2022-11-02

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管理センターからも一部できるようになりました。
image.png
image.png
テナントで基本認証がブロックされていないことも確認しておきます。
Microsoft管理センター [設定]-[組織設定] から先進認証をクリックします。
image.png
image.png
なお、先進認証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 LOGINXOAUTH2 に対応していることが判ります。

さらに調べていくと、海外のブログにヒントが。

昨年末あたりからTLS接続が必須になり、従来のSSL接続をサーバが拒否するようになった、と書かれています。
その一方で、CDOにSSL接続を指示すると実際にはSSLの後継であるTLSが裏で動いている、というコメントも寄せられています。

テナントによって挙動が違うのは、10月1日以降、Microsoftがテナントをランダムに選択して、基本認証(ここではSMTP AUTH以外のこと)のアクセスを無効にしたことも関係しているのでしょうか。こちらのコミュニティにはそのようなことが書かれています。

VPNで社内環境に接続したら送信できた、という事例も見つけました。(グローバルIPアドレスをチェックしている?)

追記
最終的にはこの情報が解決の糸口になりました。
これまでは自宅で調査していたのですが、社内から接続したところ、あっさりと成功しました。

結論

Microsoftは今後、Exchangeオンラインの SMTP AUTH も無効にする(OAuthベースの先進認証に移行していく)と考えられるので、CDOを使った方法はもう諦めた方が良さそうです。

先述と同じ人のブログですが、ノーコードツールの Power Automate でGoogleスプレッドシートと連携し、Microsoft365メールを一括で送信していました。これは素晴らしいですね!

参考ドキュメント

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?