SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|
2025|01|02|03|04|05|06|07|

2005-04-15(Fri) Rubyで添付メール送るライブラリ発掘

  今日はセッセセッセと、昨日のインポートスクリプトを利用して、過去のメールをGmailへとインポートする。Web上にもあるケド……とは思ったが、各種メーリングリストの内容も併せてインポートしてみた。検索能力の高さを考えると、いつかMLで見た情報を……って時に重宝するに違いないからだ。

You are currently using 70 MB (3%) of your 2099 MB.

  いーかげん、インポートしツカレたのにもかかわらず、いまだGoogleは挑戦的なメッセージを繰り出してくる。たった3%だって……。ちなみに、Gmailの容量は、この4月1日に1Gから2Gに拡張され、それからも徐々に容量は増加しているらしい。すると、ハンパの99MBというのはそれからの増加分であり、今回転送した70MBはその増加分にも満たないというコトか!? Google恐るべし……。

  ちなみに、昨日紹介した「Google GMail Loader」であるが、敵を知ろうと(?)サイトを見て回ったトコロ、Windows版のスクリーンショットでちょっと見慣れたアイコンを見てしまった。左上のアイコンはTkを使ってるシルシである。どーやら、Python/Tkで開発されたらしい。なんと、敵はPythonか……にしても、そのサイズはなんだよ。Pythonの処理系を含んでのサイズなのだろうが、3.6Mバイトって……。

  一方でLinux版はバイトコンパイルされたPythonのプログラムだが、サイズは一気に縮んで1/10の360kバイト。それでも360kバイトかよ。ちなみにオイラの作ったimport2gmailは641バイト。扱えるファイルの種類やエラー処理に違いはあれど、さらにその1/500以下だ。ま、単純に比較するのはヘンだけども。

  さて、それはそうと、メールのインポートが終わったので、次はバックアップストレージとして活用するためのスクリプトの開発である。とりあえず、スクリプトから添付ファイル付きのメールを飛ばす必要があるのだが、Ruby本体に添付のライブラリ集には、大したライブラリが含まれていない。

  唯一あるのが、mailread.rbライブラリのMailクラスだが、これはメールを読み出すだけで、メールを送信する機能がなく、net/smtp.rbライブラリのNet.SMTPクラスはメールを送信するだけで、メールの内容を操作する機能がない。添付ファイル付きのメールを飛ばすのに必要なのは、まさにこの間をウマくつなぐクラスなのである。

  ところが実はオイラ、かなり以前に職場でテストプログラム用に既にクラスを組んでるんだよね……ゴソゴソ……さんざん探し回ったトコロ、なんとか出てきた。ちょっと昔に組んだヤツだが、手前味噌ながら非常によくできたクラスだと思う。サンプルプログラムと一緒にまとめて置いておく。email.rbライブラリのEmailクラス、それを継承したEncodedEmailクラス、更にそれを継承したAttachedEmailクラスだ。

  このクラスを使えば、たったコレだけで既存のファイルを添付してメール送信することができる。

#!/usr/bin/env ruby
 
require 'email'
require 'kconv'
 
#-------------------------------------------------------------------------------
#
#       send attached mail
#
mail = AttachedEmail.new
mail.smtpServer      = "smtp.provider.co.jp"
 
mail['To']           = "hoge@gmail.com"
mail['From']         = "hoge@itline.jp"
mail['Subject']      = "■■■■■■■■ 添付メールテスト ■■■■■■■■".mime_encode
 
block1 = Email.new
block1['Content-Type'] = "Text/Plain; charset=ISO-2022-JP"
block1 << "This is attached mail test."
block1 << ""
block1 << "添付メールもこんなに簡単".tojis
block1 << ""
block1 << "=== Hogeta Hogeo ==="
 
block2 = EncodedEmail.new
#lock2['Content-Type'] = "Image/Jpeg; name=\"xxxx.jpg\""                # 画像を添付する場合
block2['Content-Type'] = "Application/Octet-Stream; name=\"#{"添付Mail.rb".mime_encode}\""
block2['Content-transfer-encoding'] = "base64"
block2 << open('attachfile.dat').read
 
mail << block1 << block2
mail.send

  ほとんどの指定は、メールを送るのに必須の情報を渡しているダケで、コマンド的にはnewして、<<で添付して、sendで送るという3段階だけだ。また、メールを送るだけじゃなくて受けるのも簡単。クラスをnewするときにファイルハンドラを渡してやるダケ。

#!/usr/bin/env ruby
 
require 'email'
require 'kconv'
 
#-------------------------------------------------------------------------------
#
#       receive attached mail
#
mail = AttachedEmail.new(STDIN)
 
mail.header.each {|k, v|
        print "#{k}: #{v.mime_decode.toeuc}\n"
}
 
mail.block.each {|b|
        print $/
        p b.decode
}

  勝手にインスタンスの中に取り分けてくれる。組み合わせれば、自動応答スクリプトなんかも、数十行で書ける。Ruby恐るべし、である。

  ちゅーわけで、今日はコードを貼ってお茶を濁してしまったが、明日は……明日は、明後日の情報処理試験に向けてイイカゲン勉強しなきゃだよ!! ではまた。


2012-04-15(Sun) ズタ袋を自作する

  とある理由で、気に入って以前から背負っていたズタ袋が持ち歩けなくなってしまうという都合が生じた。必死になってネットで代替品を探していたのだが、真に気に入るようなアイテムは見つからない。結局、悩みに悩んだ挙句、帆布で自作することにした。

  ついでに、より自分の描いていたイメージに近いものを作ることにした。参考のため「ズタ袋」で検索したところ「あしたのジョーの矢吹丈が持っていたアレが欲しい」という記述があちこちに見つかる。「ボンサック」という名称が一般的らしいことも知った。

  そうそう、オイラも「あしたのジョーのアレ」がイメージに近いのだ。しかし、もっと言えば「スターダスト・シティのマックが持っていたアレ」のイメージなのだけどな。とはいえ、読み返してみても、挿絵にズタ袋の姿は見つからない。文章だけなのに、頭の中にビジョンがあるというのもおかしな話なのだが、なにせハッキリとしたイメージがあるのだから仕方ない。

  早速、近所に「大塚屋」という大きな「生地屋」があるので足を運んだ。部分的に革も使いたいのでハンズにも寄る。家に年代物のミシンがあるのでマニュアルを熟読し、ミシン針とミシン糸も揃えた。それにしても、昔のミシンまで遡ってマニュアルを完備している蛇の目ミシンは素晴らしいのヒトコトだ。

  で、完成したのが以下。

  画像の説明

  口はハトメに紐を通す形。

  画像の説明

  片側の下端には革をあしらっている。

  画像の説明

  背負うとこんな感じ。帆布の風合いが心地いい。背中へのフィットもなかなか。

  画像の説明

  年代物のミシンだが、調子は完璧だった。

  画像の説明

  ミシンなんて小学生の家庭科以来だが、持ち前の器用さで、満足度95%の仕上がりである。しかし、初期投資やら、買ってはみたが余計だったものやらで、意外と大金がかかってしまった。

  実はこれは習作で、これから黒バージョンを作る予定である。ネットで検索する限り、こういうの欲しい人はほかにも多そうなので、余計にできたらオークションででも売ろうかしらん(→売ってます)。

本日のツッコミ(全2件) [ツッコミを入れる]

あうあう [こんにちは 最近ボンサックを欲しいなと思っていたのですが、中々好みのものが見つからず、色々なサイトで探していました。..]

フルタニアン(管理者) [興味を持ってもらえてありがとうございます。 ヤフオクに出してます。「ズタ袋」で検索すると出てくると思います。 製作依..]


2024-04-15(Mon) 遅ればせながら「DKIM」してみる

  「つぶやき」がメジャー化するにつれブログが衰退してきているように、各種チャットツールがメジャー化するにつれメールが衰退してきているように感じる。なんつうか「軽いノリ」が好まれるという傾向か。とはいえ、個人的には「つぶやき」では済まない記事を書くのが好きなので、このようにブログを書き続けているわけなのだが。

  個人的にメールの歴史はGmailの「前」か「後」に分かれると思う。無料にもかかわらずあまりに高機能なので個人的にメールサーバを運用する理由が消失してしまった。メーラの仕様には多少なりとも不満があるので個人的に皮を被せているが、Gmailの素晴らしさに疑う余地はない。

  そんな今日このごろだが「ドメインを勝手に使ってメールを送られないためのDNS設定」みたいな記事をふと目にして、ボチボチ「DKIM」とか何とかいうやつを勉強しておくべきかな、という気になった。つうのも、ちょっと前に神奈川県の高校入試関連システムが受験生にメールを出したが届かないトラブルが起きた、というニュースが心に引っかかっていたからだ。

  その文脈では、半ば「DKIM」が常識のように語られていたのだが、自分はほぼ聞いたことがなかった。OSサポートという仕事からは、ジャストではないものの、守備範囲としてはだいぶ近い。とはいえ、先のOAuth2.0の対応とか、Googleは攻めすぎている印象もある。

  というわけで、果たして自分は遅れているのか、それほどDKIM対応は難しいものなのか、そのヘンを明らかにするためにも、実際に設定をしてみたので以下にまとめるのである。

  まずは概念。なんか「3つくらいある」とボヤっと認識していたメール関連のセキュリティ機構だが、それは「SPF」「DKIM」「DMARC」の3つであった。「SPF」は簡単なので既に知っていたし「DMARC」は送る立場であれば必要性は薄く、重要なのは「DKIM」だけなのであった。

  「SPF」は、メール受信サーバがSMTP接続される都度、メールの「From」の送信元アドレスのドメインにDNS経由で照会し、SMTP接続してきた相手のIPが妥当か確認するものだ。DNSの汎用(TXT)レコードを流用する形の実装で、実に頭のいい実装である。

  「DKIM」は、それを先へ進めたもので、メール1通毎に「電子署名(ドメインの秘密鍵で署名)」を付けて送信し、メール受信サーバがメールを受信する都度、メールの「From」の送信元アドレスのドメインにDNS経由で「公開鍵」を要求し、メールの「電子署名」が妥当か確認するものらしい。こちらも、DNSの汎用(TXT)レコードを流用する形の実装になっている。

  「メール」「電子署名」というと、既に「S/MIME」があるじゃねーか、と思わなくもないが「S/MIME」が「個人の署名」「メーラへの実装」であるのに対して「DKIM」は「ドメインの署名」「メールサーバへの実装」という違いがある。誰もが「個人の公開鍵」を持ち、それを広く周知できる仕組みがあれば、それを使ってメールも認証すればいいわけなので「S/MIME」でもいいのだが、一般に「個人の公開鍵」を持つには金がかかる、という「セキュリティビジネス的な側面」の影響でそれができてないことに起因して、「DKIM」が生まれたという見方もできるだろう。

  別の見方をすると「組織に取り組ませる」は「誰もが取り組む必要がある」よりも格段に容易という見解も得られる。前者の例が法人税。後者の例がマイナンバ。前者と後者の中間の例がインボイス。「誰もが取り組む必要がある」ものは、仮にそれが正当でも実現は容易ではないということだ。

  やや脱線したが「DKIM」に戻る。送信時に「電子署名」の付与が必要になるが、それは「メールサーバへの実装」により行われる。具体的にメールサーバとはPostfixなのだが、そんな機能を持っているはずもない。調べていくと案の定だ。Milter機構を使って送信直前に署名処理を挟むらしい。Milter機構はsendmailの頃からあるが、個人的には気持ちのよくない実装である。

  それはそれとして、Milterの先に何を置くかというと、それは「opendkim」らしい。コマンドではなくデーモンだ。ちょっと大げさなような気がするが、処理するメールの数が多い場合は、都度プロセスを上げるより効率がいいのかしらん。

  不思議なのは「opendkim」がRHELには含まれないところ。場外の売場であるEPELでの扱いらしい。なんでも、何かRHEL要件に合わないということで、永久追放みたいな説明がある。永久追放て……ケンカでもしたのかしらん。デファクトスタンダードなGmailには必須技術なのに、デファクトスタンダードなRHELが対応しないのは矛盾だなぁ。サポートする立場としては責任放棄できる反面、扱わない説明に苦慮させられる予感がする。

  とはいえ、個人で使う分には勝手だ。まずは失敗から始めよう。何も考えず、VPS上にPostfixを起動し、自分のGmailアカウントに対してメールを送らせる。

# telnet localhost 25
mail from: xxxxxxxxxx@itline.jp
rcpt to: xxxxxxxxxx@gmail.com

  メールはPostfixには受け取ってもらえたが、PostfixとGmailサーバとのSMTPセッション内でエラーが発生して送信に失敗した。maillogには以下が記録されていた。

xxx xx xx:xx:xx xxxxxx postfix/smtp[xxxxxxx]: xxxxxxxxxx:
to=<xxxxxxxxxx@gmail.com>, relay=gmail-smtp-in.l.google.com[74.125.23.27]:25, delay=21, delays=20/0.03/0.81/0.81, dsn=5.7.26, 
status=bounced (host gmail-smtp-in.l.google.com[74.125.23.27] said: 
550-5.7.26 This mail has been blocked because the sender is unauthenticated. 
550-5.7.26 Gmail requires all senders to authenticate with either SPF or DKIM. 
550-5.7.26  
550-5.7.26  Authentication results: 
550-5.7.26  DKIM = did not pass 
550-5.7.26  SPF [itline.jp] with ip: [xxx.xxx.xxx.xxx] = did not pass 
550-5.7.26  
550-5.7.26  For instructions on setting up authentication, go to 
550 5.7.26  https://support.google.com/mail/answer/81126#authentication xxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxx  - gsmtp (in reply to end of DATA command))

  ちゃんと「SPFもDKIMも通っていない」と返された。改めて失敗させよう。DNSにSPFレコードを足してやる。

# cat /var/named/external.itline.jp
@               IN  TXT     "v=spf1 +ip4:xxx.xxx.xxx.xxx -all"

  すると意外なことにGmailアカウントにメールが届くようになった。ただし「迷惑メール」の中にではあるが。

  と、ここで満を持してDKIM様がリングに上がるのである。

# dnf install opendkim opendkim-tools
 
# opendkim-genkey -D /etc/opendkim/keys -d itline.jp
# ls /etc/opendkim/keys
default.private  default.txt
# chown opendkim:opendkim /etc/opendkim/keys/*
 
# vi opendkim.conf
# diff opendkim.conf.org opendkim.conf
< Mode	v
> Mode	s
< Umask	002
> Umask	000
< # KeyTable	/etc/opendkim/KeyTable
> KeyTable	/etc/opendkim/KeyTable
< # SigningTable	refile:/etc/opendkim/SigningTable
> SigningTable	refile:/etc/opendkim/SigningTable
 
# vi KeyTable
# diff KeyTable.org KeyTable
> default._domainkey.itline.jp itline.jp:default:/etc/opendkim/keys/default.private
 
# vi SigningTable
# diff SigningTable.org SigningTable
> *@itline.jp default._domainkey.itline.jp
 
# systemctl start opendkim
# systemctl status opendkim
# netstat -anp | grep dkim
unix  2      [ ACC ]     STREAM     LISTENING     181622904 3273917/opendkim     /run/opendkim/opendkim.sock
 
# ls -l /run/opendkim/opendkim.sock
srwxrwxrwx 1 opendkim opendkim 0  4月 13 20:54 /run/opendkim/opendkim.sock=
 
# chown opendkim:mail /run/opendkim
# ls -l /run | grep dkim
drwxr-x---  2 opendkim       mail             60  4月 13 20:54 opendkim/
 
# diff main.cf.org main.cf
> smtpd_milters = unix:/run/opendkim/opendkim.sock
> non_smtpd_milters = $smtpd_milters
> milter_default_action = accept
 
# cat /etc/opendkim/keys/default.txt >> external.itline.jp
# systemctl reload named-chroot

  ほぼ書いてあるどおりの内容だが、権限関係で少し引っかかった。「Umask 000」と「chown opendkim:mail /run/opendkim」だ。これをしないとソケットの権限の都合で、Postfixがopendkimへの接続に失敗し、署名が付かない。opendkimのパッケージングバグという印象も感じるが……EPEL扱いと関連があるのかしらん。なんにせよ設定を済ませたら、改めて自分のGmailアカウントに対してメールを送らせる。

# telnet localhost 25
mail from: xxxxxxxxxx@itline.jp
rcpt to: xxxxxxxxxx@gmail.com
 
# tail /var/log/maillog
xxx xx xx:xx:xx xxxxxx opendkim[xxxxxxx]: xxxxxxxxxx: DKIM-Signature field added (s=default, d=itline.jp)

  ちゃんとログに「署名を足したゼ」という報告が出ている。よっしゃよっしゃ……と、Gmailを開くが、メールがちっとも来ない……と、思ったら「迷惑メール」じゃなくて「受信トレイ」に届いていた。そらそうか。

  Gmailでは、メールを開いて、左上の「︙」アイコンから「メッセージのソースを表示」を実行することでDKIMの認証結果を確認することができる。

SPF:	PASS(IP: xxx.xxx.xxx.xxx)。詳細
DKIM:	'PASS'(ドメイン: itline.jp)詳細

  ならばよし! これにて「DKIM」対応は完了である。ま、別に使わないけどさ。

  ちなみに上で必要性は薄いと書いた「DMARC」だが、「DKIM」と同列に語られるものの、別にセキュリティレベルが向上するわけでもなんでもなく、DKIM関連の情報をやりとりするというだけの機構だ。送る立場であればDNSの設定に以下を加えるくらい。

_dmarc          IN TXT      "v=DMARC1; p=quarantine; rua=mailto:xxxxxxxxxx@gmail.com"

  この追加により、Gmailの認証結果に「DMARC」が加わる。「PASS」ってのもヘンだな。一応、メールアドレスを書いておいたら、結果がメールで届いたが。

SPF:	PASS(IP: xxx.xxx.xxx.xxx)。詳細
DKIM:	'PASS'(ドメイン: itline.jp)詳細
DMARC:	'PASS' 詳細

  つうわけで「DKIM」について十分に理解が進んだわけだが、それほど難しいわけでもないものの、RHELでは真っ当に使えない「opendkim」が必要というのは微妙。しかしそれとしても、メールサーバを立てるのにGmailに考えが及ばなかったシステム屋はちょっと十分にアレだと言える気がするな。拒否された際のエラーメッセージもこれ以上ないくらいにわかりやすいし。

  それはそれとしても、考えるほどに「SPF」だけで十分な気がするんだよな……と、ふとRFC化はされているのかいな、と思って調べてみると、3つともされているものの、なんと「SPF」は「DKIM」の後にRFC化されているようだ。え?それって、どういうこと? 「DKIM」は「SPF」を先へ進めたもの、じゃない?そういうこと?