アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

メールサーバーの設定まとめ(postfixとdovecot)

こんにちは、牧野です。久々のブログになりました。。

2年くらい、インフラに関する仕事がメインでしたが、最近ここ2、3ヶ月はフロント側を作ることが多くなっています。
javascriptを触ることも多くなり、夏休みには以前作ったandroidアプリの百人一首のHTML版を作ったりしていました。よかったら遊んでみて下さい。
http://demo.asial.co.jp/~makki/karuta/
スマートフォンgoogle chrome推奨です。

さて、今日の話題はjavascriptやプログラミングではなく、メールサーバー設定の話です。
もう何ヶ月か前になりますが、postfixを使ってメールサーバーを立てる機会があったので、その時の設定をまとめようと思います。

やりたかったことは大きく分けて以下の3つです。
・バーチャルドメイン、バーチャルメールボックス
pop3メール受信
SMTP認証

■バーチャルドメイン、バーチャルメールボックス
postfixのパッケージをインストールすると、メインとなる設定ファイルは/etc/postfix/main.cf です。
以下の設定ではメールのドメインは makmakmak.asia です。


myhostname = mail.makmakmak.asia
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination =
#relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.2 ...
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
virtual_mailbox_domains = makmakmak.asia, localhost, localhost.localdomain, localhost
virtual_mailbox_base = /var/spool/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 100
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

myhostname: 自サーバーのホスト名を記載
mynetworks: メール送信元となる全サーバーのIPを追加
virtual_mailbox_domains: メールアドレスで使うドメインを全部記述
virtual_mailbox_base: このディレクトリ内にドメインディレクトリが作成され、その中に各ユーザーのメールディレクトリが作成されます
virtual_uid_maps, virtual_gid_maps: 今回は、メールファイルを触るユーザのユーザーID、グループIDを5000番に指定

5000番のユーザー、グループにはvhostsユーザー、グループを用意します。


useradd -u 5000 vhosts


POP3メール受信
postfixdovecotと組み合わせて使用します。(dovecotはバージョン1.1系)

/etc/dovecot/dovecot.conf


protocols = pop3 pop3s
log_path = /var/log/dovecot.log
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/var/spool/mail/vhosts/%d/%n
mail_uid = 5000
mail_gid = 5000
mail_privileged_group = mail
protocol pop3 {
  pop3_uidl_format = %08Xu%08Xv
}
auth default {
  mechanisms = plain cram-md5 apop
  passdb passwd-file {
    args = /etc/dovecot-passwd
  }
  user = root
}
auth_debug = yes


mail_location: postfixのvirtual_mailbox_base, /etc/postfix/vmailbox の記載と合わせる(%dはドメイン名、%nはユーザー名)
mail_uid, mail_gid: postfixの virtual_uid_maps, virtual_gid_maps と合わせる

パスワードの設定は /etc/dovecot-passwdに書きます。


makki@makmakmak.asia:{CRAM-MD5}hogehoge...

CRAM-MD5は認証で使う方式で、{CRAM-MD5}の後ろのhogehoge...の部分は暗号化したパスワード文字列です。
この文字列は、以下のコマンドを実行してパスワードを入力すると出力されます。


dovecotpw -s CRAM-MD5

auth_debug = yes があるとログに詳細が出力されます。最初の受信確認ができるまで入れておくといいと思います。


smtp認証
以下はSMTP認証もdovecotで行うための設定です。
postfixの /etc/postfix/main.cf に2行追加します。


smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth


dovecotの /etc/dovecot/dovecot.conf には、
auth default内に socket listen のブロックを追加します。



auth default {
  mechanisms = plain cram-md5 apop
  passdb passwd-file {
    args = /etc/dovecot-passwd
  }
  user = root
  socket listen {
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = postfix
    }
  }
}

インターネットプロバイダによっては、外部の25番ポートにアクセスできないようになっていることがあります(OP25B: Outboud Port 25 Blocking)。
その場合の対応として、SMTP認証を通れば587番ポート(Submissionポート)を使ってメールを送信できるようにします。

/etc/postifx/master.cf
下記3行の先頭#を消して、設定を有効にします。


submission inet n       -       -       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

変更したら、postfixdovecotをリロードします。


/etc/init.d/postfix reload
/etc/init.d/dovecot reload




…とここまで書いてきましたが、最近のディストリビューションでインストールされるdovecotパッケージはバージョン2系になっていて、設定ファイルの書き方がけっこう変わっていました。。
バージョン2系では、/etc/dovecot/conf.d 内に役割ごとの設定ファイルがいろいろあり、それを使って設定するようになっています。
単純にdovecot.confを置き換えても動かないので、dovecot2系で動作確認できたらまた追記しようと思います。。


以下、追記です。

■dovecot2系の設定ファイル
dovecot1から2にバージョンアップして、設定ファイルを直しました。
今回は、/etc/dovecot/conf.d 内の.confファイルをすべて読み込んでいたのをやめて、/etc/dovecot/conf.d/10-master.conf だけ読み込むようにしています。



protocols = pop3
log_path = /var/log/dovecot.log
log_timestamp = "%Y-%m-%d %H:%M:%S "
ssl_cert =</etc/ssl/certs/dovecot.pem
ssl_key =</etc/ssl/private/dovecot.pem
mail_location = maildir:/var/spool/mail/vhosts/%d/%n
mail_uid=5000
mail_gid=5000
mail_privileged_group = mail
mail_debug = yes

protocol pop3 {
  pop3_uidl_format = %08Xu%08Xv
}

auth_mechanisms = cram-md5 apop plain
passdb {
  driver = passwd-file
  args = /etc/dovecot-passwd
}

!include /etc/dovecot/conf.d/10-master.conf
auth_verbose=yes
auth_debug=yes
auth_debug_passwords=yes

mail_debug = yes
auth_verbose=yes
auth_debug=yes
auth_debug_passwords=yes
デバッグ用です。
conf.d 内のファイルを読み込む設定は、もともと
!include /etc/dovecot/conf.d/*.conf
になっています。

/etc/dovecot/conf.d/10-master.conf


service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  user = root
}


dovecot1と2の主な変更点は以下の通りです。
・conf.d内の.confファイルの読み込み
・protocol のpop3 1つで、pop3とpop3sの両方OKに
ssl_cert_file => ssl_cert, ssl_key_file => ssl_key
・auth default {...} => service auth {...}
・auth defualt内にあったpassdbが外に出て、passdb内にdriver設定追加
・auth default内にあったmechanismsが外に出てauth_mechanismsに
・socket listen ... => unix_listener ...

dovecotをリスタートした時のメッセージとログのデバッグ出力を見ると、設定ファイルの修正箇所が見つけやすいと思います。

無料で使えるメール配信アプリケーション

こんばんは。笹亀です。

今週よりアシアルでは健康診断な季節に入っております。自分もバリュームをいただける年齢になりまして、初バリュームで見事に発泡剤にやられました・・・

先のブログで再熱しそうな「スパイシーチキン」ですが、辛いものが苦手な自分にはスパイシーチキンは刺激的すぎで1度も食べたことがありません。そのかわりに「海苔唐揚げ明太」の担当としてデビューをしようと思っております。先週も今週も週1以上のペースで食べています。打倒、スパイシーチキンを掲げてみたいとおもいます。
 ※海苔唐揚げ明太をみたいかたはこちらをどうぞ

さて本日は、「無料で使えるメール配信アプリケーション」をご紹介させていただこうと思います。メルマガを送信する際に、外部のサービスを使用するとどれも毎月の定額課金でお金がかかってしまい、非常にコストがかかってしまい困ることがここ最近多いです。

自分で実装するにも手間がかかる問題やエラーメールで送信できなかったときの処理などメールを送るといっても作成するのも大変な感じです。そんなことを思い、メール配信するアプリケーションを自分で作成せずに手軽に実装ができ、無料で提供しているものを探していました。

そんな同じ悩みをお持ちの方、お待たせしました。
ありました!みつけました!

acmailer」というアプリケーションです。


ライセンスも用途にあわせた4つのライセンスから選択できるのでとてもいいです。設置も簡単でperlsendmailが動くサーバをお持ちならば簡単に設置ができます。
設置フォルダと付属のinstall.cgiパーミッションを設定し、install.cgiを実行します。その後、設定作業をおこなうだけですぐに利用が可能な状態になります。



自社運営のサイト内に設置ができてCSV取り込み機能もあるので外部システムからメアドのリストを取り込み、手軽にメルマガ送信の配信ができてとても便利です。
他にも携帯電話にも対応しておりテンプレートをわけて配信することも可能です。テキストメールの他にもHTMLメール、デコメールも配信ができます。

EC CUBEみたいなアプリケーションで手軽に利用する分には十分です。
必要とされる一通りの機能が実装されておりますので、ぜひ皆さんもお使いになってみてはいかがでしょうか。

XPathでメール処理する「Mail_mime_XPath」を作ってみました。

こんにちは、亀本です。

相変わらずPerlわからないのにCPANのライブラリ群にお熱です。
以前、tomi-ruさんの日記で、Email::MIME::XPathというのがちょろっと紹介されていたんですが、これがとても便利そうだなーと思って垂涎たらしていました。

PHPでも、もちろんEmail::MIMEみたいなことができるPEAR::Mail_mimeというライブラリ群があるのですが、やはりforeachなどを使ってぐるぐる回して目的のデータを探す、という処理を毎回記述することになります。
これはやはり不便だし、いちいちmultipartの階層を気にしたりせず、もっとサクッとデータを取得したいな、と思いますよね。


ということで、PHPでも似たような感じでXPath式によってメールのデータを取得できるライブラリ「Mail_mime_XPath」を作成してみました。

ソースコードCodeReposに突っ込んでおいたので、適当に使ってあげてください。ちっちゃなライブラリです。
なお、使用する際にはPEARのMail_mimeパッケージもインストールしておく必要があります。

使い方ですが、



<?php 
require_once 'Mail/mime/XPath.php';

$doc = file_get_contents('hoge.eml');

$email = new Mail_mime_XPath($doc);
$part = $email->xpath('//*[@ctype_primary="text"]');

var_dump($part);


上記のように、メール本文からインスタンスを生成し、XPathで検索をかけるだけです。
上記の処理だけで、メールからtextパートのヘッダとデータの配列を取得することができます。


内部的には、PEARのMail_mimeDecodeでパースしたデータをもとに、SimpleXMLを使ってデータをXMLに直したうえで、XPathで検索、取得という処理をしています。

XPathで検索できる対象ですが、検索対象のデータ自体がMail_mimeに依存している関係から、Mail_mimeで配列のキーになっているものがXPathのノード名として使えます。
また、
・content-type
・ctype_primary
・ctype_secondary
・filename
という4つのデータだけは、各パートのプロパティとしても保持されているので、上記の例のようにこれらのプロパティで検索することによって、textパートの一覧とそのデータを抜き出すことが可能です。
PerlのEmail::MIME::XPathと違って正規表現的な方法は使えませんが、元々content-typeが分割されているので必要な処理はわりと柔軟に行うことができます。


勢いで作ったのでまだまだ荒削りですが、もっと洗練させることでもっとがっつり便利になるんじゃないかなと思っています。
ぜひぜひ使ってみたり修正してCodeReposにコミットしてみたりしてください。

symfonyでSwift Mailerを使用する際の注意点

2008.12.03 やっぱり使い方を間違っていなかったようなので、再修正です。田舎の開発者さんご指摘ありがとうございました。

2008.08.28 Swift_Messageの使い方を間違えるという、とっても初歩的なミスをしていたので、修正しました。 shuwat さんありがとうございました


先日のsymfonyのjpMailPlugin(メール送信プラグイン)の使い方のまとめのコメントで、Swift Mailerについてshuwatさんがコメントで言及されていたので、Swift Mailerについて軽くふれておきます。

とりあえず、symfonyのCookbookに書いてある通りに進めればできます。

symfony1.0 であってもgetPresentationFor()メソッドを使用して同様にメール送信することもできます。

SMTPを使用したメールのであれば、以下のコードで送信することができると思います。



<?php
// ...省略
// 2008.08.28 修正
/*
$msg = new Swift_Message(
  'サブジェクト',
  mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  'text/plain',
  '7bit',
  'iso-2022-jp'
);
*/
// 2008.12.03 再修正
/*
$msg = new Swift_Message(
  'サブジェクト',
  '本文',
  'text/plain',
  'iso-2022-jp',
  '7bit'
);
*/
$msg = new Swift_Message(
  'サブジェクト',
  mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  'text/plain',
  '7bit',
  'iso-2022-jp'
);
$conn = new Swift_Connection_SMTP('localhost');
$mailer = new Swift($conn);

$mailer->send($msg, 'to@example.com', 'from@example.com');
// ...省略


ソースコードUTF-8で記述されていれば、これで本文が ISO-2022-JP のメールが送信されるのですが、SubjectヘッダーはUTF-8の状態で送信されます。そのため、メールのソースを見ると以下のようになってしまいます。



Subject: =?utf-8?B?44K144OW44K444Kn44Kv44OI?=


Thunderbirdの場合、うまくデコードしてくれるのですが、その他のメーラーでもデコードできるかどうかは不明です。特に携帯メールの場合は怪しいと思います(おそらく絵文字を件名に入れたりはできないかと思われます)。

なお、ISO-2022-JP の件名を作成することも可能で、以下のようにします。



<?php
// ...省略
/*
$msg = new Swift_Message(
  mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  'text/plain',
  '7bit',
  'iso-2022-jp'
);
*/
/*
$msg = new Swift_Message(
  mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  '本文',
  'text/plain',
  'iso-2022-jp',
  '7bit'
);
*/
$msg = new Swift_Message(
  mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  'text/plain',
  '7bit',
  'iso-2022-jp'
);
$msg->headers->setCharset('ISO-2022-JP');
// ...省略


これでSubjectヘッダーは以下のように変更されます。



Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIGyhC?=


一見これでうまくいったかのように見えるのですが、件名が長い場合の折り返し処理で不都合が生じます。たとえば、「サブジェクトサブジェクトサブジェクト」とした場合には件名が文字化けを起こします。そのときのメールヘッダーは以下のようになります。



Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIJTUlViU4JSclLyVIJTUlViU4?=
 =?ISO-2022-JP?B?JSclLyVIGyhC?=


なお、mb_encode_mimeheader()を使用すると以下のようになります。



Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIJTUlViU4JSclLyVIJTUlViU4GyhC?=
 =?ISO-2022-JP?B?GyRCJSclLyVIGyhC?=


JISコードで使用するエスケープシーケンスを各行の最後に追加していないため、このようなことが起きてしまいます。

Swift_Mailer の内部的な処理としてヘッダーのエスケープ処理(Swift_Message_Headers)が記述されているので、mb_encode_mimeheader()を使用してエンコードする処理に変更する必要があります(もしくはSwift_Message_Headersを直接変更してしまいます)。

とは言ってもそこまでする必要はあまりないかと思います。普通に symfony1.1 でも jpMail を使用できないことはないので、そちらを使った方が今のところは良いと思います。