GAE/Java:GAEで独自ドメインのメールを送る

GAEでメールを送る場合は、管理者のメールアドレスと、Googleアカウントでログインしているユーザ自身のメールアドレスからメールを送信できるということはわかっていたのだけれど、どうすれば、Fromのメールアドレスを独自ドメインのアドレス指定できるんかなーと思っていたのですが、方法がわかりました。

結論から書くと、、、

独自ドメインのメールアドレスを管理者として招待する

以上!!

と書いたらあまりにも不親切かもしれない・・・。まぁこれだけなんですが。

一応、やりかたを順番に。


  1. AppEngineの管理画面より、AdministrationのPermissionsを選択する。

  2. Fromにしたい独自ドメインのメールアドレスに管理者としての権限を与えるためにアプリ招待メールを送る。
  3. 招待メールを受け取った独自ドメインのメールアドレスより、招待を受諾(Accept)する。
  4. 晴れて管理者になったよ!
  5. 独自ドメインアドレスを送信元にしてメール送信のテストしてみてOKなら成功

以上です。


GAE/Java:メールを送信する

GAEでメール送信するの、どうしたらいいんやろーと思っていたのですが、本にサンプルが載っていて非常に簡単でした。送るだけなら。深くはやってないのでひとまずメモ。今回は自分のサイトのお問い合わせページを作るために調べているので、いうなれば自分宛にメールしています。だから、すごく簡単になってます。

GAEでメールを送る送信元のメアドは、

  • 管理者のメールアドレス
  • Googleアカウントでログインしているユーザ自身のメールアドレス
  • 電子メール受信で使うことのできるメールアドレス

となっています。これはアドレス偽装してメール送信するのを防ぐためです。
一番簡単にメールを送る方法としては、管理者のメールアドレスを使ってしまうことです。今回はそうしています。

JavaMail APIとLow level APIの2つの方法がありますが、今回はLow level APIを使っています。本にこちらのほうが簡単と書いてあったので(^_^;)たしかにすごく簡単でした。

※ソースコードはSlim3のコントローラーです。validateなどは一切行っていません。

public class IndexController extends Controller {

    @Override
    public Navigation run() throws Exception {
        if (isPost()) {
            // POSTされたデータを取得
            HashMap<String, Object> input = new RequestMap(request);
            String name = input.get("name").toString();
            String mail = input.get("mail").toString();
            String subject = input.get("subject").toString();
            String body = input.get("body").toString();
            Message message = new Message();
            message.setSender("********@gmail.com"); // 管理者のアドレス
            message.setTo("****@********.com");  // 宛先を設定
            message.setSubject(subject);
            message.setTextBody("名前: " + name
                + "\n\nメールアドレス: " + mail + "\n\n"
                + body);
            MailService ms = MailServiceFactory.getMailService();
            // メールを送信する
            ms.send(message);
            return forward("index.jsp");
        } else {
            return forward("index.jsp");
        }
    }
}

シンプル過ぎる・・・。大した例じゃなくてすみません。

参考にした書籍は以下になります。データストア以外の情報は超便利な気がする。


Android:HTTP通信でGET, POSTする

WebAPIをバンバン使うアプリを作っていたわりに、微妙にJavaでのHTTP通信の方法をよくわかってなかったのですが、ようやくちょっとわかったのでメモっときます。今まではライブラリでやっていました。

API Level 8からAndroidHttpClientというのがあるらしいんですが、今回はあえてDefaultHttpClientで。

以下、GET

// 例外処理は省いています
// パラメータを生成
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("subject", "件名"));
params.add(new BasicNameValuePair("body", "本文です。こんにちは!"));
// パラメータをクエリに変換
String query = URLEncodeUtils.format(params, "UTF-8");
HttpGet httpGet = new HttpGet("http://www.example.com/?" + query);
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse httpResponse = client.execute(httpGet);
// ステータスコードを取得
int statusCode = httpResponse.getStatusLine().getStatusCode();
// レスポンスを取得
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);
// リソースを解放
entity.consumeContent();
// クライアントを終了させる
client.getConnectionManager().shutdown();
// 後はステータスコードやレスポンスを煮るなり焼くなり

以下、POST

// 例外処理は省いています
// パラメータを生成
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("subject", "件名"));
params.add(new BasicNameValuePair("body", "本文です。こんにちは!"));
HttpPost httpPost = new HttpPost("http://www.example.com/");
// パラメータを設定
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse httpResponse = client.execute(httpPost);
// ステータスコードを取得
int statusCode = httpResponse.getStatusLine().getStatusCode();
// レスポンスを取得
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);
// リソースを解放
entity.consumeContent();
// クライアントを終了させる
client.getConnectionManager().shutdown();
// 後はステータスコードやレスポンスを煮るなり焼くなり

という感じっぽいです。

割と色々とやっているのに、こういう初歩的なことで詰まったりするので、基本をもっとちゃんとやらないといかんなぁと思いました。やっても忘れるので、俺俺ライブラリ作るか、こうやってブログにまとめておくか…。

ちなみに参考にした本は、横山さんの本です。

マッシュアップアプリを作りたい人にとっては、すごく参考になると思います!


Android:XOOM買いました!

タイトルの通りですが、AUから発売されたAndroid 3.0のタブレット、XOOMを買いました!ええ、もちろん開発用ですよ、開発用!!開発用ですってば!!ひゃっほーい!!では写真をどうぞ!

XOOMの箱の表

XOOMの箱の表

XOOMの箱の裏

XOOMの箱の裏

XOOMの中身全部

XOOMの中身全部

XOOMの起動ロゴ:モトローラー

XOOMの起動ロゴ:モトローラー

XOOMの起動ロゴ:Android AU

XOOMの起動ロゴ:Android AU

動いている最中の写真は撮ってないので、写真はここまで。
まだタブレット用のアプリがあんまりないので、iPadと比べたら微妙なんでしょうが、Androidタブレットはこれからですから。一応、自分の目的であった、XOOMでi文庫 for Androidを使って電子書籍を読むというのは、ちゃんとできました。しかも、かなりいい!これがダメなら電子書籍のためだけにiPad買おうかと思っていましたが、買う必要なくなりました。

LuvPadとくらべ、ちゃんとソフトウェアキーボードの大きさも打ちやすいので、これといって不満ないですね。まぁUIが微妙と言われればそうですが。タブレット用OSになっているから、メニューボタンからではなくActionBarメインのUIになってます。慣れの問題なんでしょうねぇ。

開発用にも使うし、読書用にも使うし、活躍してくれそうです!!(^_^)


Android:現在地情報を取得する方法を修正

Androidアプリ、計画停電情報で、現在地の取得が遅い!取れない!と結構言われていました。自分のテストでは取れていたのですが、なんかおかしそうだったので、今回修正しました。

まぁ決まって言われるのは、「Google Mapsならすぐ取れるんですが」なんですよ。それはわかってます、と…。Mapを使えば、MyLocationOverlayが使えるから、取りやすいのかなと思ってはいたけれど、開発当初は、Mapを使わないでいいようにしようと思っていたから、敢えてonLocationChangedだけで勝負していたわけです。でもダメっぽかった…。取れる人は取れるけど、取れない人は取れないという…。

地図機能を追加したから、MyLocationOverlayを使った方法にしようと思って修正しました。そのときに使ったコードの一部を公開しときます。全部見たい人はgithubからとってくださいw
まぁ具体的にはMyLocationOverlayを継承して、MyLocationOverlay側のonLocationChangedに処理を追加したという感じです。これ便利ですねー、ほんと。

// MapActivityを継承したclassのprivate class
/**
 * 現在地を取得したらその場所に移動する機能をもったオーバーレイ
 * 呼び出し元のActivityから現在地を取得ボタンを押された場合のみ、そのような動作をする
 */
private class CustomMyLocationOverlay extends MyLocationOverlay {
    /** 呼び出し元から現在地取得が押されて呼ばれたかのフラグ */
    private boolean isMyLocationRequestByTop;
    /** 初回表示時に、マップを現在地に移動させるフラグ */
    private boolean isFirst = true;
        
    public void setIsMyLocationRequestByTop(boolean requestByTop) {
        this.isMyLocationRequestByTop = requestByTop;
    }

    public CustomMyLocationOverlay(Context context, MapView mapView) {
        super(context, mapView);
    }

    @Override
    public synchronized void onLocationChanged(Location location) {
        super.onLocationChanged(location);
        if (isFirst) {
            isFirst = false;
            GeoPoint p = getMyLocation();
            mGeoPoint = p;
            mMapController.animateTo(mGeoPoint);
            // ピンのオーバーレイを設定するメソッド
            setOverlay(mGeoPoint);
            if (isMyLocationRequestByTop){
                isMyLocationRequestByTop = false;
                mProgress.dismiss();
                // 現在地が取得できたので、現在地情報を設定して
                // 呼び出し元のActivityに戻すメソッドを呼び出す
                callFinish();
            }
        }
    }
}

計画停電情報のDL数も13万くらいになってきました。
もっと使いやすいアプリにできるように頑張りたいと思います。