それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

curl でSMTP経由のメール送信(本文、添付ファイル、写真、BCC、CC)

curlsmtp 経由でメールを送信する。

curl で送信できる。めっちゃ便利だわこれ。

シンプルなメール

curl -v --url 'smtp://127.0.0.1:2525' \
    --mail-rcpt  admin@exp.tld\
    --mail-from  takuya@exp.tld \
    -T - <<EOS
To: takuya@exp.tld
From: takuya@exp.tld
Subject: this is a test 

this is a test using smtps

EOS

シンプルメールなのにコマンドはシンプルじゃない.

メールを送るには「本文=To:,From,Subject, body」が必要だからどうしても長くなる。

シンプルなメール(手抜き版)

お手軽に送りたい。上記のようなちゃんとしたメールを投げるのは大変ですよ。

curl -v --url 'smtp://127.0.0.1:2525'  \
  --mail-rcpt takuya@ex.tld \
 --form-string text='hello'

かなり省略している。多少エラーが出るかもしれないが、届くはずである。

これはメールボディを作らずに「テキストファイルを添付」してる。

手抜きしまくりです。でもほとんどのサーバー相手では、これでサクッと送信できる。

CC の例

メールは封書なので、封書(Envelope=mail-from,mail-rcpt)と本文(To: , CC: ) で分けて書く必要がある。

curl -v --url 'smtp://127.0.0.1:2525' \
 --mail-from  admin@exp.tld \
 --mail-rcpt  takuya@exp.tld \
-T - <<EOS
To: takuya@exp.tld
CC: admin@ex.tld
From: admin@exp.biz
Subject: this is a test BCC/CC

this is a test using smtps
EOS

添付ファイル付き

curl -v --url 'smtp://127.0.0.1:2525'  \
--mail-rcpt takuya@example.tld \
--form "sample-file=@/home/takuya/project/.gitignore"

curlSMTPでは、メールを送るときは、「本文」が添付ファイルとして扱う。 一方で、添付ファイルがある場合は、Multipartになる。本文もマルチパートになるが、そのへんはサクッとかける。

Base64エンコードするもの(写真など)

ただ、上記の場合は、エンコードが必要なファイルが多重エンコードされておかしくなる。壊れる。そこで、写真やTar.gzやZipファイルなどは次のようにする。

curl -v --url 'smtp://127.0.0.1:2525'  \
--mail-rcpt takuya@example.tld \
--form "photo=@out.png;encoder=base64"

詳しくは、man curl に書いてある。

メール本文

cat <<EOS > sample-mail.txt
To: takuya@exp.tld
CC: admin@ex.tld
From: admin@exp.tld
Subject: this is a test BCC/CC

this is a test using smtps
EOS

curl -v --url 'smtp://192.168.1.1:2525' \
  --upload-file sample-mail.txt \
  --mail-from takuya@example.com \
  --mail-rcpt takuya@example.com

冒頭の cutl -T - はこの「添付ファイル」を入れた処理である。 -T-T / --upload-file であり同じ意味である。

ファイルを添付する

単純にファイルを添付する

curl -v --url 'smtp://127.0.0.1:2525'  \
  --mail-rcpt takuiya@example.tld\
  -F photo=@/path/to/sample.txt

マルチパートのファイルは、-F --form 項目として取り扱う。

BCC

BCC は mail-rcpt (recipient) を複数書く

curl -v --url 'smtp://192.168.1.1:2525' \
  --mail-from takuya@example.com \
  --mail-rcpt takuya@example.com
  --mail-rcpt boss@example.com
...

SMTPプロトコルでは、Envelope指定でRCPT TO: addr を使う。

このときBCCならSTMP通信中にRCPT TO: addr RCPT TO: addr2 と複数回書く。

なので、--mail-rcpt が複数回登場する。

実際のcurl通信ログの例

* Connected to 127.0.0.1 (127.0.0.1) port 2525 (#0)
< 220 localhost says welcome!
> EHLO acid
< 250-localhost at your service!
< 250-8BITMIME
< 250-SMTPUTF8
< 250 OK
> MAIL FROM:<admin@example.tld>
< 250 OK
> RCPT TO:<admin@example.tld>
< 250 OK
> RCPT TO:<takuya@example.tld>
< 250 OK
> DATA
< 354 Enter message, ending with "." on a line by itself

このように、BCCは配送される。

curl で送信が便利。

SMTPプロトコルを喋るために、sendmail や snail を覚えなくて済む。

何より、SMTPメールサーバーを指定できるのが嬉しい。sendmail コマンドとだとローカル配送から考えないといけないし。

smtpTELNETで接続してメール送信テストしなくて済む。 ポート解放をしておけば、あとあと困らないでメール送信ができますね。

curl って万能ですね。

ELHO ホスト名を指定する場合

Postfixをポートフォワーディングで使っていて、 Helo command rejected: need fully-qualified hostname となる場合

curl -v --url 'smtp://192.168.1.1:2525/smtp.example.com' \
  --mail-from takuya@example.com \

このように、スラッシュのあとに、EHLOのホスト名を追記すればいい。

curl で smtps で gmail 経由する場合

メールのログインとパスワードを追記したら SMTP-AUTH を経由してSMTPSでメールが送信できる。

curl --url "smtps://smtp.gmail.com:465" \
\ 
 --ssl-reqd --mail-from "sender@gmail.com"  \
 --user "sender@gmail.com:senderGmailPassword" \
\
 --mail-rcpt "example@gmail.com"\
 --upload-file /var/scripts/mail.txt \

GMAILのメール送信もcurl で1行でできるので、google の 「 less scure app ( 安全性の低いアプリ)」が1ヶ月未使用ならオフにされちゃうので定期的にログインしておくのに良さそう

postfix 相手にSMTPS (SSL / starttls ) で、オレオレ証明書

Postfixオレオレ証明書を使っていて、Submissionポート 587 を通して接続する場合

startls は内部がSMTPなので、smtp:// を使う。smtps ではない。ただし、starttls でSSLを使うので --ssl をつける。さらに、証明書がオレオレ証明書なので -k / --insecure をつける。

curl -v --url 'smtp://10.185.93.22:587/mailcow.example.com' --ssl -k

さらに、それが、SMTP Auth を経由する場合

curl -v --url 'smtp://10.185.93.22:587/mailcow.example.com'  --user "takuya@example.com:PASSWORD" --ssl 

なんかオプションが増えて大変だけど、ちゃんと送信できる。

TO / FROM を正確に記述する

curl は to(recpt) / from をSMTPプロトコルにつかうので、メールの本文のFROM/TOは書き換えは行われない。当然であるが。

メールのボディを指定して、FROM/TOとSubjectを正確に記載すると普通のメールとして送信が可能。SMTPの動作チェックであればなくても構わないので上記まででは省略してた。

echo 'To: takuya@example.com
From: takuya@mydomain.tld
Subject: this is a test from 465

this is a test
using smtps
' \
| curl -v --ssl --url 'smtps://mailcow.mydomain.tld:465' \
   --mail-from service@mydomain.tld \
   --mail-rcpt takuya@example.com \
   --user "account@mydomain.tld:XXX_PASS_XXX" \
   -T -

ここでは、--mail-from と、ボディの From: と、--user は、敢えてすべて異なるようにしている。SMTPではこれらを一致させる必要はなく、実際にこれで送れてしまうのだ。

一般のメールだと、拒否されるかもしれないが、smtp replay に直接投げ込みできると送信が可能なのである。

そして、From:が受信者のメーラーで表示されるはずだ。 ---mail-fromsmtp プロトコルだし、--userSMTP Auth用である。ややこしいですがそういうものなんでしょうね。

curl はほとんどの環境で使える。

curlWindows に添付された ( C:/Windows/System32/curl.exe ) ので、すべての環境で使えるコマンドになった。

curl未インストールは、 alpine や debian 軽量版など、特殊状況に限られるようになった。

curl だけでメールは送れるし、コマンド呼び出しで使えるのである。

メールプログラムを書く、ライブラリをインストールするなど、車輪の再発明するくらいならcurl でいいのである。

2022-03-15 追記

EHLOについて追記。

SMTP + start TLS について追記。

2022-03-16 追記

メールボディ指定、FROM / mail-fromについて追記。

2024-09-08 追記

BCCについて追記。

CCに付いて追記。

コマンドを整理してパイプをなくすなど

写真の添付がうまくいかなったので調査した。

参考資料

https://stackoverflow.com/questions/10523147/what-are-the-curl-smtp-command-line-arguments-to-support-gmail-tls-starttls-v

16 Command Examples to Send Email From The Linux Command Line

Sending email - everything curl