質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.64%

サーバーからのメールの一斉配信機能において、無効なメールアドレスに何度も送りつけるのを防ぐ機能を実装したい

受付中

回答 5

投稿

  • 評価
  • クリップ 4
  • VIEW 5,288

cDm_48

score 170

現在運営しているwebサービスにメールの一斉配信機能をつけようと思っております。

webサービスの方は
・apache
・rails
 で運用しております。


メール一斉配信機能をつけるにあたり、一番懸念していることは無効なメールアドレスに何度も送りつけてしまうことです。

これを防ぐためにはどういったことをしてあげればよいのでしょうか?
(質問1)

無効なメールアドレスを手作業で消していくのではなく、機械的に消していって欲しいです。
※消すといっても、論理削除などを考えております。

また、メールの一斉配信において、ゆくゆくはターゲットを絞り込んでの配信などをしていきたいのですが、こういうのはpostfixなどで出来ますでしょうか?(postfixで出来る場合は、入れるべきライブラリを、それ以外の場合は、どういうソフトウェアがよいか教えて頂けませんか?)
(質問2)

有償でメールの一斉配信が簡単にできるソフトはたくさんありますが、
社内の技術力アップも踏まえ、今回はオープンソースのソフトウェアを用いて社内開発していきたいと考えております。

とはいえど、社内にメール配信機能を実装したことがある方がいないため、手探り状態です。
お手数ですが、ご教示頂けると幸いです。

宜しくお願いします。


  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+2

幾つかの回答で、バウンスメール(エラーメールとかリターンメールと呼ばれたりもする)を元にメールの送信失敗を検出する方法が示されていますが、バウンスメールから元の送信先メールアドレスを導出する方法について。

メール送信時の Return-Path を次のような形式にします(MTA が postfix 場合)。

bounce+{送信先メールアドレスごとに一意な値}@oreore.example.com


{送信先メールアドレスごとに一意な値} は、送信先メールアドレスごとに採番されたIDのようなものでもいいし、送信先メールアドレスを適当にエンコードした文字列でも良いです。

{送信先メールアドレスごとに一意な値} の前の + は、MTA(Postfix とか qmail とか)によって異なりますが、拡張メールアドレスと呼ばれるもので、bounce+ext  の ext の部分がどのような文字であったとしても、同じ宛先として扱うことができる機能です。

これを利用することで、bounce+ から始まるすべてのメールを1つのプログラムで処理させることができるので、前述のように + 以降の部分に元の送信先アドレスが特定出来る情報を埋め込んでおけば、バウンスメールから直ちに元の送信先アドレスを特定することができます(バウンスメールの中身を解析しなくても、バウンスメールで返ってきたことだけなら簡単に判断できる、ということです)。


バウンスメールをプログラムで処理させる方法ですが、大抵の MTA ではメールの受信時に特定のプログラムにメールを渡すことができるようになっています。

例えば、postfix ならユーザーのホームディレクトリに .forword というファイルを次のような内容で作成しておけば、メールの受信時にそのプログラムを実行させることができます。

|/path/to/program

bounce というユーザーを作成し、そのホームディレクトリに .forword.forword+default だったかもしれない)というファイルを上のような内容で作成しておけば、送信したメールがバウンスメールとして帰ってくるたびにそのプログラムが実行されるようになります。

bounce ユーザーを作らなくてもトランスポートマップとかでどうにかする方法も考えられますけれども)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

メールの不達にはいろいろなパターンがありますが、

1. ドメインが存在しない。または期限が切れている
2. ドメインが存在しているがユーザーが存在していない
3. メールボックスがいっぱいである
4. 送信したメールが大きすぎる

3,4についてはいずれ回復するかもしれないので無効にする必要はない。
1,2については無効にする

ruby についても下記記事を見る限り、php と仕組みは同じようなので、php で検証コードを書きますね。

Rubyでメールを送る

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once('PHPMailer/class.phpmailer.php');

function send($strRecipient)
{
    mb_language("japanese");
    mb_internal_encoding("UTF-8");

    $mail = new \PHPMailer();
    $mail->CharSet = "iso-2022-jp";
    $mail->Encoding = "7bit";

    $mail->AddAddress($strRecipient);
    $mail->From = "送信アドレス";
    $mail->FromName = mb_encode_mimeheader(
        mb_convert_encoding(
            "送信アドレス"
            , "JIS"
            , "UTF-8"
        )
    );
    $mail->Subject = mb_encode_mimeheader('テスト送信');
    $mail->Body = mb_convert_encoding(
        'テスト送信'
        , "JIS"
        , "UTF-8"
    );

    if (!$mail->Send()) {
        echo $strRecipient . ":" . $mail->ErrorInfo . "\n";
    } else {
        echo $strRecipient . ":" . "success\n";
    }
}

$email = array(
    'valid_user@exist_domain'
    , 'invalid_user@exist_domain'
    , 'invalid_user@invalid_domain'
);

foreach ($email as $strRecipient) {
    send($strRecipient);
}
いずれも「送信成功」になってしまいます。

プログラムで送信時に取得できるのはあくまで、sendmailやpostfix などのミドルウェアに処理を渡したことについて成功したか失敗かを取得します。

精度の高い仕組みにするには、送信アドレスに帰ってくるエラーメールを定期的にメールボックスをチェックし、エラーメールの本文を解析して該当の送信先アドレスを無効にするという仕組みになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/13 21:29

    ソースコードと共に、わかりやすい解説有り難うございます。

    phpもしくはrubyでのソースコード内ではメールの不達を検知することは難しいということですよね?

    Kousukeさんが仰られていた「送信アドレスに帰ってくるエラーメールを定期的にメールボックスをチェックし、エラーメールの本文を解析して該当の送信先アドレスを無効にするという仕組み」というのを一度考えてみたいと思います。

    キャンセル

  • 2015/08/13 21:31

    > phpもしくはrubyでのソースコード内ではメールの不達を検知することは難しいということですよね?
    難しいではなく、不可能です。

    キャンセル

  • 2015/08/13 23:48

    不可能なんですね。有り難うございます。

    キャンセル

+1

perl製ですが、こんなツールもあります。
ひょっとしてお役に立ちませんか?
bouncehammer

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/13 23:52

    URLの共有有り難うございます。
    すべてを見きれておりませんが、すごく役立ちそうです。

    社内でこういったツールを作れたらなって思ってましたが、
    既存のツールを使うのもありですね。

    参考にさせて頂きます!

    キャンセル

+1

メールを送信する際にリターン先メールアドレスも設定しておきます。
届いたリターンメールをCRON等で定期チェックしてメールアドレスを抽出し、3回送れなかったらそれ以降は送らないなどの処置とします。
リターンメールを返すかどうかは相手のサーバー次第ですのであて先不明(ドメインは有るがメールアドレスが無い場合など)の場合は何も返ってこない場合が多いです。と言うのは、リターンメールによるサーバーの負荷やトラフィック増大を防ぐ理由によるものです。また、リターンメールの書式は相手サーバーの自由ですのでメールアドレス自動抽出プログラムは高い頻度で見直す必要が有るかも知れません。
そもそも相手先が存在しない場合(ドメインが無いなど)は送信先が存在しないのでリターンメールが返ってくることは有りません。(サーバーによっては送信元サーバーが送信者に何らかのメッセージを返すかもしれません)。送信元サーバーでメールキューに保留となり、何回かの送信リトライ後の数日後にはキューは消去されますがこれもチェックする必要があるでしょう。メールキューの確認は通常ルート権限が必要です。
リターンメールには様々なエラーコードが付加されてきます。これもチェックして適切な振り分けを行った方がいいでしょう。
不完全なまま運用を開始するとあなたの収容されているサーバーがスパムメール送信元と同じ扱いになってしまう恐れがあり、周囲のサーバーも巻き込んでブロックリスト(ブラックリスト)に登録されてしまい、あなたのサーバーからのメールは相手サーバーが拒否するようになってしまうかもしれません。
https://ja.wikipedia.org/wiki/DNSBL
例えば  SPAMHAUS(https://www.spamhaus.org/)にブラックリストとしてあなたのサーバー(IPアドレス)が登録されてしまった場合で、受信元がスパムメール防止策の一つとしてSPAMHAUSを参照していた場合、メールは受け取り拒否されてしまいます。この場合は、SPAMHAUSへ登録解除申請を行います。通常数日後には解除されます。SPAMHAUS以外にも同様なサービスはすぐに100団体以上見つかります。例えばこちらで自サーバーのIPアドレスを入れて、ブラックリスト登録されていないか一括チェックできます。http://whatismyipaddress.com/blacklist-check
この様なサービスは色々あり、「blacklist check」で検索するといくつか見つかります。
つまり、エラーコードを見て受け取り拒否されているか否か、理由も確認する必要があります。
と、実装する機能が多岐にわたります。
よって、送信先が少なければ問題は起きにくいでしょうけど、十分注意いただくことをお願いしたいです。
私もこれら問題を全て経験してきました。結局メール送信ASPを使う方がコストが安いことに気づき、今現在はメール一斉送信の運用は有りませんが、その時が来たら外部サービスを使用するつもりです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/14 16:06

    色々と有益な情報有り難うございます。
    一度勉強のためにも自社構築を試みて、コスト面等も考え、
    メール送信ASP等も視野にいれ、考えていきたいと思います。

    先人の方々の知恵を拝借でき、非常に助かります。

    キャンセル

-1

メールは送付してみないと実際に届くかどうかわかりません。ただ、キャリアからスパムアカウントとして扱われたりしてユーザーに届かないこともありうるので、いきなり論理削除をするのもまずいでしょう。

1. 送付してみてエラーが発生したらエラーカウントをインクリメント
2. 送付してみて成功したらエラーカウントを0にする
3. エラーカウントが一定数を超えたアカウントを論理削除

というのはいかがでしょうか?

SMTPもエラーコードが定義されています。4xxや5xxです。これらに該当するコードが送信時に返ってきたら上記のカウント処理を行ってみてはいかがでしょうか?

参考: SMTP/POP3 プロトコルエラー応答一覧

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/13 16:48 編集

    上記の回答に対するツッコミのつもりで書いたんですが、わかりにくかったですね。回答に差し替えます。

    キャンセル

  • 2015/08/13 16:53

    こちら回答ですよね。コメントになってしまってます。

    キャンセル

  • 2015/08/13 21:31

    ご回答有り難うございます。
    エラーカウントをインクリメントして一定数以上になると論理削除というやり方は非常に興味深く、勉強になりました。

    これらを参考にメール配信機能実装に取り組もうと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • Apacheに関する質問
  • サーバーからのメールの一斉配信機能において、無効なメールアドレスに何度も送りつけるのを防ぐ機能を実装したい