IT系おじさんのチラシの裏
2018年10月~
当サイトの記事にはアフィリエイト広告のリンクが含まれる場合があります

PHPでIMAPを使いメールの本文を取得する例

前回の記事「PHPでGmailの受信トレイのメール一覧を取得する例」ではGmailへIMAP接続し、メールの一覧(タイトルのみ)を取得する例を紹介しました。

今回は引き続き、メールの本文を取得する例です。

前提

前回の記事でIMAPの接続とメール一覧を取得するところまでは書いてあるハズですので、そこにgetBodyというメール本文を取得する関数を組み込む感じで進めます。

■サンプルコード

//Gmailのアカウント情報
$cfg['GMAIL_ACCOUNT'] = '[Gmailのメールアドレス]';
$cfg['GMAIL_PASSWORD'] = '[Gmailのパスワード]';

//Gmailの接続情報
$cfg['MAILBOX'] = '{imap.gmail.com:993/imap/ssl}';

//IMAP接続
if (($mbox = imap_open($cfg['MAILBOX'], $cfg['GMAIL_ACCOUNT'], $cfg['GMAIL_PASSWORD'])) == false) {
	echo 'Gmailへの接続に失敗しました';
} else {
	//メールボックス情報を取得
	$info = imap_check($mbox);
	$max = 50;//最大50件取得
	for ($i = 0; $i < $max; $i++) {
		$msgno = $info->Nmsgs - $i;
		if ($msgno <= 0) break;
		//メールのヘッダー情報を取得
		$header = imap_header($mbox, $msgno);
		//メールのタイトルを取得
		$subject = getSubject($header);
		echo $msgno.':'.$subject.'<br>';
		echo '<textarea>'.getBody($mbox, $msgno).'</textarea>';
	}
	imap_close($mbox);
}

PHPでIMAPメールの本文を取得する例(手抜き版)

■サンプルコード

//メール本文の取得(マルチパート非対応)
function getBody($mbox, $msgno)
{
	$body = imap_body($mbox, $msgno);
	$body = mb_convert_encoding($body, 'UTF-8', 'auto');
	return $body;
}

解説

PHPのimap_body関数で本文を取得し、文字コードの変換もautoで任せてしまうという手抜きっぷり。

でも、昔ながらのiso-2022-jpなテキストのみのメールならこれだけでけっこう動きます。

特に「いろんな作業を自動化してWeb運営を楽にしよう」というコンセプトでPHPスクリプトの紹介をしている当ブログとしては、メール送信するのも受信するのも自分のプログラムだったりするので、ぶっちゃけコレだけでも良いかな、と思わなくもありません。

PHPでIMAPメールの本文を取得する例(もう少し真面目版)

■サンプルコード

//メール本文の取得(マルチパートほんのり対応)
function getBody($mbox, $msgno)
{
	//マルチパートだろうとそうでなかろうと1個目を取得する
	$body = imap_fetchbody($mbox, $msgno, 1, FT_INTERNAL);

	//メールの構造を取得
	$s = imap_fetchstructure($mbox, $msgno);

	//マルチパートのメールかどうか確認しつつ、文字コードとエンコード方式を確認
	if (isset($s->parts)) {
		//マルチパートの場合
		$charset = $s->parts[0]->parameters[0]->value;
		$encoding = $s->parts[0]->encoding;
	} else {
		//マルチパートではない場合
		$charset = $s->parameters[0]->value;
		$encoding = $s->encoding;
	}

	//エンコード方式に従いデコードする
	switch ($encoding) {
		case 1://8bit
			$body = imap_8bit($body);
			$body = imap_qprint($body);
			break;
		case 3://Base64
			$body = imap_base64($body);
			break;
		case 4: //Quoted-Printable
			$body = imap_qprint($body);
			break;
		case 0: //7bit
		case 2: //Binary
		case 5: //other
		default:
			//7bitやBinaryは何もしない
	}
	//メールの文字コードをUTF-8へ変換する
	$body = mb_convert_encoding($body, 'UTF-8', $charset);
	return $body;
}

解説

いきなり長くなりましたが、これでも完全と言えるかどうかは微妙なところ。

1行目でいきなりその理由がわかるかと思いますが、

	//マルチパートだろうとそうでなかろうと1個目を取得する
	$body = imap_fetchbody($mbox, $msgno, 1, FT_INTERNAL);

このとおり、マルチパートメールだろうとそうでなかろうと、1個目のメール本文を取得しています。

そもそもマルチパートメールとはなんぞや、という話ですが、1つのメールの中に異なる形式のデータを含むメールのことです。

例えば添付ファイル付きのメールが良い例ですが、あれは1個目にメール本文、2個目に添付ファイルをエンコードした文字列が並んでいるだけのものです。なので、その場合、1個目のメール本文だけわかれば良いよね、ってことで1個目しか取得していません。

また、HTMLメールの場合、それを読めないメールソフトのことを考え、1個目にテキストメール、2個目にHTML、と並べているケースがあります。まぁ最近だいぶ少なくなりましたけどね。HTMLメールが読めないメールソフトなんてほとんどないやろ、という風潮もありますのでw

ともあれ、どっちにしろ、これも1個目のメール本文だけ読めれば良いんじゃないかな…という理由(言い訳)で上記のような作りにしました。本気でメールソフトレベルのモノが作りたい場合は$s->partsが連想配列になっていますので、ループして本文を取得すると良いでしょう。

文字コードについて

マルチパートの場合は1個目のパラメーターから文字コードを取得しています。

		$charset = $s->parts[0]->parameters[0]->value;

マルチパートじゃない場合は $s->partsがないため、下記のとおり、parameters[0]から取得です。

		$charset = $s->parameters[0]->value;

どちらの場合も $charset にはUTF-8やらiso-2022-jpやら、メール本文で使われている文字コードの名称が入ってきますので、それに従って最後の最後に mb_convert_encoding しているという寸法。

エンコード方式について

メールの場合、気にするのは文字コードだけではないのですよね。エンコード方式が8bit / Base64 / Quoted-Printableだったりするので、それに従って変換をしています。7bitは何も処理する必要がないのと、binaryとotherは見たことがないのでそのままスルーしています(手抜き)。

まとめ

  • メール本文を簡単に取得するならimap_body関数を使う
  • 但し、メール本文がBase64などにエンコードされている可能性がある場合はimap_fetchstructureでメール構造と文字コードとエンコード方式を調べて、それぞれ適切に変換する必要がある

といったところでしょうか。

マルチパートのメールについてはもうちょい真面目にやろうかなとも思ったのですが、うーん、やっぱり自動化処理においては1つ目の本文だけ取得できれば良いよなぁ…としか思えなかったので、これ以上サンプルが長くなるよりは、ということで手抜き版とさせて頂きました。

とりあえず、ここまで作れれば、例えば自動的にメールチェックして、本文中のリンクをブラウザで全部開く、とか簡単に自動化できると思います。もちろんそれによってSPAMメールを自動で開いたら大変なので、差出人やURLのチェックとかも必要ですけどね。

関連記事

Windows環境にphpmyadminをインストールする

最近のレンタルサーバーなら管理ページでポチっとボタンひとつでphpmyadminのインストールくらい完了しますし、手動でやるとしても公式サイトからZIPをダウンロードして解凍してアップロードする程度で

Windows版PHPでSFTP接続するにはphp_ssh2.dllが必要

Web運営のメンテナンス作業(ローカルへのバックアップ作業とか)を自動化する方法について4回にわけて記事にしてきました。 WSHでブラウザを自動操作する PHPでファイルとDB(Postgre

コメント

新しいコメントを投稿する

[新規投稿]
 
TOP