GnuTLSを使ったドコモメールの送信がエラーになる

9 views
Skip to first unread message

Masamichi Hosoda

unread,
Feb 21, 2026, 3:00:26 AM (yesterday) Feb 21
to mew...@googlegroups.com, true...@trueroad.jp
細田です。

GnuTLSを使用してドコモメールの送信をしようとすると

```
502 Command not implemented. This mail has been queued to +queue
```

と出てきて送信できないという事象があり、
原因と思われるものがわかったので報告しておきます。

ドコモメールの送信サーバ設定は
https://www.docomo.ne.jp/service/docomo_mail/other/
にある通り、

SMTPサーバ
smtp.spmode.ne.jp
ポート番号
465

となっていて、STARTTLS不要で最初から暗号化されているものです。
以下の設定で再現できます。

```.el
(setq mew-smtp-server "smtp.spmode.ne.jp")
(setq mew-smtp-ssl 'native)
(setq mew-smtp-ssl-port 465)
(setq mew-smtp-user "te...@example.com")
```

この設定で適当なメールを送信しようとするとMew-debugは以下のようになります。

```
<TLS proto=smtp, server=smtp.spmode.ne.jp:465, starttlsp=nil>
verify-level=1, network-security-level=medium, nowait=nil, tlsparams=gnutls-x509pki :priority NORMAL:%DUMBFW :hostname smtp.spmode.ne.jp :loglevel 0 :min-prime-bits 2048 :trustfiles (/etc/ssl/cert.pem) :crlfiles nil :keylist nil :verify-flags nil :verify-error nil :pass nil :flags nil :callbacks nil :priority-string NORMAL:%DUMBFW

<=SEND=>
EHLO localhost

<EHLO>
503 Bad sequence of commands


<=SEND=>
HELO localhost

<HELO>
502 Command not implemented


<=SEND=>
QUIT

<QUIT>
221 Service closing transmission channel


<SMTP SENTINEL>
connection broken by remote peer
```

EHLOに失敗してHELOも失敗してエラーが出たということがわかります。
一方、
gnutls-cli --port 465 smtp.spmode.ne.jp
のようにして普通に接続して手動でEHLOを発行してやると普通に成功します。

Mewから接続した場合とgnutls-cliで接続した場合で
何が違うのかかなり悩んだのですが、どうもMewが使っている
open-network-streamの中でEHLOを発行してcapabilitiesを取得しており、
戻ってきた後でMewが再度EHLOを発行し、2度目のEHLOに失敗している
のではないか、ということがわかりました。

Mew-debugをみてもEHLOは1回しか登場しませんが、
mitmproxyを使って通信内容をみたところ2回発行されています。

まず、Mewの設定を以下のように変更します。

```.el
(setq mew-smtp-server "localhost")
(setq mew-smtp-ssl 'native)
(setq mew-smtp-ssl-port 8080)
(setq mew-smtp-user "te...@example.com")
```

次にmitmproxy (mitmdump)でキャプチャしながら
メール送信しようとすると以下のような内容が得られました。
(`--ssl-insecure`が無いとlegacy renegotiaionで失敗する)

```
$ mitmdump --mode reverse:tls://smtp.spmode.ne.jp:465 --ssl-insecure --set flow_detail=3
[15:35:06.903] reverse proxy to tls://smtp.spmode.ne.jp:465 listening at *:8080.
[15:35:27.816][[::1]:56308] client connect
[15:35:27.828][[::1]:56308] server connect smtp.spmode.ne.jp:465 (49.102.153.242:465)
[::1]:56308 <- tcp <- smtp.spmode.ne.jp:465

220 ESMTP Server Ready

[::1]:56308 -> tcp -> smtp.spmode.ne.jp:465

EHLO localhost

[::1]:56308 <- tcp <- smtp.spmode.ne.jp:465

250-docomo.ne.jp
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-SIZE 15727616
250 8BITMIME

[::1]:56308 -> tcp -> smtp.spmode.ne.jp:465

EHLO localhost

[::1]:56308 <- tcp <- smtp.spmode.ne.jp:465

503 Bad sequence of commands

[::1]:56308 -> tcp -> smtp.spmode.ne.jp:465

HELO localhost

[::1]:56308 <- tcp <- smtp.spmode.ne.jp:465

502 Command not implemented

[::1]:56308 -> tcp -> smtp.spmode.ne.jp:465

QUIT

[::1]:56308 <- tcp <- smtp.spmode.ne.jp:465

221 Service closing transmission channel

[15:35:31.185][[::1]:56308] server disconnect smtp.spmode.ne.jp:465 (49.102.153.242:465)
[15:35:31.185][[::1]:56308] client disconnect
```

上記のようにmitmproxyでみていると
1回目のEHLOは成功していますが2回目のEHLOは失敗しています。
この時のMew-debugも2回目のEHLO以降だけが見えていて、1回目のEHLOは見えません。

おそらく、世にある多くのSMTPサーバは
EHLOが2回発行されても普通に処理してくれるので発生しないが、
smtp.spmode.ne.jpは2回目がエラーになるため発生する事象なのかなと思います。

次になんでopen-network-streamが中でEHLOを発行しているのかというと、
STARTTLS用にcapabirities取得のためのパラメータを渡しており、
本来STARTTLS不要で最初から暗号化されている場合でも
capabilitiesを取得するためEHLOを発行する動作になっている、
のではないかと思います。
実際、返り値を確認してみるとcapabilitiesが得られていました。

以上、まずは事象のご報告をさせていただきました。

---
細田 真道 <true...@trueroad.jp>

Masamichi Hosoda

unread,
4:56 AM (9 hours ago) 4:56 AM
to mew...@googlegroups.com, true...@trueroad.jp
細田です。

> GnuTLSを使用してドコモメールの送信をしようとすると
>
> ```
> 502 Command not implemented. This mail has been queued to +queue
> ```
>
> と出てきて送信できないという事象があり、
> 原因と思われるものがわかったので報告しておきます。

について、パッチを作ってみましたのでpull requestしました。
https://github.com/kazu-yamamoto/Mew/pull/212

手元では、件のsmtp.spmode.ne.jp:465のメール送信の他、
SMTP, POP, IMAPそれぞれについて、
STARTTLSでアップグレードする時の動作と
STARTTLS不要で最初から暗号化されている時の動作、
いずれも問題なく動作することを確認しております。

修正内容としてはopen-network-stream関数を呼び出す際に、
STARTTLSが必要な時だけSTARTTLS用のパラメータを渡し、
不要な時はnilを渡すようにしました。

また、この変更をするとSTARTTLS不要で最初から暗号化されている時に
open-network-stream関数がgreetingを吸い込まなくなり、
非暗号化時と同様にMewで受信するようになるため、
greeting処理をスキップする条件を非STARTTLSに限定しました。

合わせて、関連する動作で不統一なところなどの修正を入れてあります。

マージしていただければ幸いです。


以下、修正方法を検討した際に調べた情報を書いておきます。

まずopen-network-stream関数の:always-query-capabilities
パラメータをnilにしてやればEHLOを発行しなくなって
問題解決できるのではと考えました。

mew-ssl.elにあるmew-ssl-native-starttls-plistの設定が使われるのですが
SMTP, IMAP, NNTPはt
POPはnil
にしているようです。
(POPだけ違う理由はわかりません)

そこで、ここのSMTPのところをnilにしてみましたが
EHLOが発行される挙動は変わりませんでした。

一応、open-network-stream関数がある
emacsのnetwork-stream.elを確認してみたところ、
:always-query-capabilitiesの効果があるのは
:typeがplainの時だけのようです。

emacsのドキュメントで:always-query-capabilitiesの説明を読んでも
plainの時の挙動しか書いてありません。

問題となっているopen-network-stream関数の呼び出しでは
:typeはtls(最初から暗号化)かstarttls(STARTTLSでアップグレード)かの
いずれかだけしかないので:always-query-capabilitiesの設定は
あまり意味がないということになると思います。

ここで、open-network-stream関数を呼び出すと実行される、
greetingを吸い込んで、capabilityを取得して、
STARTTLSを発行して、再度capabilityを取得する、
という一連のSTARTTLS動作はGnuTLSが持っているのではなくて
emacsのnetwork-stream.elに実装してあることに気がつきました。
勝手にGnuTLSの機能だと誤認していましたが、
emacsの機能だったのですね。

:typeがtls(最初から暗号化)の時は、
:end-of-commandがあるとgreetingを吸い込む、
:capability-commandがあるとcapabilityを取得する、
という動作になっています。

もちろんSTARTTLSが必要な時はこれらのSTARTTLS関連パラメータを渡さないと
STARTTLSの動作ができなくなりますが、STARTTLSが不要な時は渡さなければ
greetingを吸い込んだりcapabilityを取得したりしなくなります。
capabilitlyを取得しないようにすればEHLOの発行も止められます。

というわけでpull requestしたように、
STARTTLSが必要な時だけSTARTTLS用のパラメータを渡し、
不要な時はnilを渡す修正にしました。

---
細田 真道 <true...@trueroad.jp>
Reply all
Reply to author
Forward
0 new messages