GAEでメール受信&メール送信 〜勝手に思ってるサークルの問題点に、勝手に取り組む #2〜

移転しました。

勝手に思ってるサークルの問題点に、勝手に取り組むシリーズ 第二弾~新入生メールアドレス自動登録編~ 
joymail

やりたいこと

煩雑なメール登録作業の軽減がしたい!!
毎年、新入生歓迎の時期になると多くの新入生がサークルに集まってくる。うちのサークルでは、Gmailを使って連絡を行っている。そのため、その度に何10人、最終的には100人規模でメールアドレス登録するという地獄の作業が待っている。これはなかなか辛い。

ちょっと前までは、紙にアドレスを書いてもらっていた

いままでは、紙にアドレスと名前を書いてもらって、後で転記、メールアドレス登録、メール送信という手段を取っていたみたい。

んなアホなっ!!!!

案の定、記入者の記入ミス、転記者の転記ミス、登録者の登録ミスが多発。せっかくアドレスを書いてもらっても、情報を伝える大切な機会を失っていた。

そこで、
自分は、次の方法に切り替えた。

  1. Gmailアドレスのエイリアス(+freshman)を使って新入生勧誘用のGmailアドレスを生成
  2. 新入生勧誘用のGmailアドレスのQRコードを生成
  3. そのQRコードをケータイで読み取ってもらい、名前(と大学名)だけ入れてもらい送信
  4. Gmail側で新入生のフィルリング処理

これによって、転記ミスの大幅軽減に成功!!それでも、アドレスを管理するために、結局は、アドレスを登録するという作業は残されている。

そこで、
Google App Engineを使って、メール受信して、名前とメールアドレスをパース。それをDB登録。そこからGmailのアドレス帳を出力できるようにすれば便利なんじゃ?

と考えた。が、当時は、そこまでの技術はなくて断念。若干時間にゆとりのある今だからこそ、改めて挑戦したい!!!


ってことで、まずはGAEでメール受信&送信にチャレンジ

GAEでメール受信&メール送信

Google App Engineでのメール受信とメール送信なんて、公式ドキュメントにも載ってるしまずは簡単に出来るだろうっ!って思ってた自分が間違いでした。チュートリアルを見ても全然上手くいかない。色々と、探しているうちに、次のページを見つけて参考(流用・・・)にさせてももらいました!ありがとうございます!!!

Google App Engine for Javaでのメール受信コード -きしだのはてな
http://d.hatena.ne.jp/nowokay/20091024


これでやっと、メール受信、そのメールを送った先のメールアドレスとの本文を丸ごと取得、本文をそのまま取得したメールアドレスに送信という流れができました。ソースを↓に載せておきます。

次回の作業

次は、メール受信から本文のパースとDB登録です。パースは、調べれば出来そうですが、DB登録がなかなかのくせ者のよう。まずは、BigTableの概念を掴まないと始まらないですね。



明日は今日とは違う自分になる

金曜日は、ジュンク堂にいき、常々欲しいと思ってた2冊の本を買いました。「情熱プログラマー」と「自分の小さな「箱」から脱出する方法」の2冊です。2冊とも、Twitterでオススメされた本なので、非常に楽しみです。また、気付いたこと、感じたことをまとめたいと思います。

明日は今日とは違う自分になるでした。


package javamail;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class JavaMailServlet extends HttpServlet {
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		resp.setContentType("text/plain");
		resp.getWriter().println("Hello, world");

		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		try {
			MimeMessage message = new MimeMessage(session, req.getInputStream());

			MimeMessage mail = new MimeMessage(session);
			mail.setSubject(message.getSubject());
			//ローカルサーバーでは文字化けするので次のようなコードが必要。本番サーバーでは不要
			//mail.setSubject(new String(message.getSubject().getBytes("8859_1"), "UTF-8"));
			//返信元アドレスを構成
			URL url = new URL(req.getRequestURL().toString());
			String senderAddress = "echo@" + url.getHost().replace("appspot", "appspotmail");
			Address sender = new InternetAddress(senderAddress);
			mail.setFrom(sender);
			mail.setRecipient(Message.RecipientType.TO, message.getFrom()[0]);
			//mail.setRecipient(Message.RecipientType.TO, TO);
			
			String contentType = message.getContentType();
			InputStream is = null;
			//2009/12/11 挙動がかわったことに対応
			String mess = "";

			if(message.isMimeType("text/plain")){
				//ふつうのメールの処理
				/* 2009/12/11 ここも挙動が変わってたので、ClassCastExceptionになります。
	                is = (InputStream) message.getContent();
				 */
				mess = (String)message.getContent();
			}else{
				//HTMLメールや添付メールの処理
				/* 2009/12/3 挙動が変わったのでこれではClassCastExceptionが発生する
	                Multipart content = new MimeMultipart(
	                        new ByteArrayDataSource(
	                            (InputStream)message.getContent(), 
	                            message.getContentType()));
				 */
				Multipart content = (Multipart)message.getContent();

				for(int i = 0; i < content.getCount(); ++i){
					BodyPart bp = content.getBodyPart(i);
					if(!bp.isMimeType("text/plain")) continue;
					is = bp.getInputStream();

					contentType = bp.getContentType();
					break;
				}
			}
			if(is != null){
				//contentTypeからエンコーディングを取得
				String encoding = null;
				String[] elms = contentType.split(";");
				for(String elm : elms){
					if(elm.trim().startsWith("charset=")){
						encoding = elm.trim().substring("charset=".length());
					}
				}

				Reader r = null;
				if(encoding != null){
					//エンコーディングが入っている
					if(encoding.startsWith("\"")) encoding = encoding.substring(1);
					if(encoding.endsWith("\"")) encoding = 
						encoding.substring(0, encoding.length() - 1);
					r = new InputStreamReader(is, encoding);
				}else{
					//エンコーディングが入っていない
					r = new InputStreamReader(is);
				}

				//2009/12/11 挙動がかわったことに対応
				//String mess = "";
				BufferedReader buf = new BufferedReader(r);
				for(String line; (line = buf.readLine()) != null;){
					mess += line + "\n";
				}
				//2009/12/11 挙動がかわったことに対応
				//mail.setText(mess);
			}
			//2009/12/11 挙動がかわったことに対応
			mail.setText(mess);
			Transport.send(mail);

		} catch (MessagingException ex) {
			ex.printStackTrace();
		}
	}
}