2009年10月27日火曜日

メールに添付されているファイルを取得する

ちょい苦労したけど、これで行けそう。

class MailHandler(InboundEmailHandler):
def receive(self, message):
attachment = message.attachments # ここ注意
binarydata = message.[1].payload.decode(message[1].encode)

でもこれは、添付ファイルが一つの場合のみ。
添付ファイルが一つの時は、message.attachmentsはtupleで(添付ファイル名, EncodePayloadオブジェクト)
となっている。
添付ファイルが二つの時は、message.attachmentsはlistで、[(添付ファイル名, EncodePayloadオブジェクト), (...)]となっている。
さらに添付ファイルがない時には、messageにattachmentsがそもそも存在しない。
それも踏まえて、場合分けをする必要があるようだ。

http://groups.google.com/group/google-appengine/browse_thread/thread/8bf0ab058eb3fcb3/dc447ee56ef59890?lnk=raot

2009年10月25日日曜日

GAEで受信したメールの件名を取得する

これでいけるようだ。

class MailHandler(InboundEmailHandler):
def receive(self, message):
header = decode_header(message.subject)
subject = ''
for s, charset in header:
if charset:
subject += unicode(s, charset)
else:
subject += s

無条件でunicode(s, charset)とやってしまうと、件名が英語だけの時にcharsetがNoneになる事があるので注意しよう。

Google App Engineでメール受信できた人いる?

Google App Engine 1.2.6からメールを受信する機能が追加された。
これは便利だと早速試してみたけれども、なかなかうまく行かない。
ネットで調べてみても、「できるようになったらしいよ」とGoogleやGIGAZINEのニュースを引く人はいるけれども、実際に受信したとかあるいはいろいろトラブったという話は、ヒットしない。Googleのサイトも英語は説明あるけど日本語の説明がないのもちと怪しい。

とにかく、今の事象を書いておくとする。だれか助けて。

[開発サーバでの話]
app.yamlに以下の設定をする。

- url: /_ah/mail/.+
script: main.py
login: admin

そして管理コンソールからメールを送ると、次のメッセージが出る。
Message send failure
Current logged in user is not authorized to view this page

まあ、(login:adminとしているので)そりゃそうなんだけど、じゃあどうしろと?


[本番サーバでの話]
駄目もとでデプロイして、regist@appid.appspotmail.com宛にメールを送ると、こんなつれない返事が返ってくる。
��ちなみにappidは、"http://appid.appspot.com/"のappidと合わせてあります)

This is an automatically generated Delivery Status Notification

Delivery to the following recipient failed permanently:

regist@appid.appspotmail.com

----- Original message -----
��以下略)



理由半分くらい判明
開発サーバでlogin:adminで入れないのは、まあしょうがないみたい。
本番サーバでうまく行かなかったのは、app.yamlに次の設定を入れていなかったから。
inbound_services:
- mail
最初は入れていたんだけど、ソースを編集しているときに削除されてしまったみたい。
これがなくても開発サーバの管理コンソールからメールが送れてしまったのが、原因発見が遅れた原因。
無事googleさまからメールが届いて一安心。

2009年10月19日月曜日

smtp2webをMac OS X(10.5)で動かす

GAEではメールを受信するアプリを作るときには、smtp2webを使う必要があるけれども、いちいちサーバにデプロイしないとテストができない。非常に不便なので、何とかmac上でローカルにsmtp2webをサービスとして起動できないかどうか確認する。

1. smtp2webのインストール
smtp2webのソースコードは公開されているので、subversionを使ってチェックアウトする。
チェックアウトフォルダは、とりあえずログインしているユーザーの書類フォルダに展開。

2. smtp2webの起動
そのままだとsmtp2webは動かない。server/smtpserver.tacファイルの修正が必要。具体的には-uにroot、-gにdaemonを指定する。
runserver.shファイルがあるフォルダに移動して、sudoコマンドを使ってrunserver.shを起動する。

3. (以下作成中)

GAEが1.2.6からメール受信機能を用意したので、smtp2webは使用しない事にした。
そのため、調査も終了〜。

2009年10月12日月曜日

PILをMac OS 10.5 (Leopard)に入れる

Google App Engineでは、画像処理を行うためのサービスが提供されている。
このサービスをローカルでも使うためには、MacにPILをインストールする必要がある。
http://code.google.com/intl/ja/appengine/docs/python/images/overview.html#Development_Server

このPILをMac OS 10.5に入れるに大変だったので、備忘録として記述。

1. PILのインストール
dmgファイルをダウンロードしてインストールしようとすると、途中でインストーラーが「このディクスにはpythonが入っていない」という警告を出して、次に進めなくなる。これは、dmgの代わりにソースをダウンロードして、コマンドラインからインストールするのがよいようだ。

Finder -> アプリケーション -> ユーティリティ -> ターミナル
$cd (ダウンロードしたtar.gzファイルを展開したディレクトリ。"setup.py"ファイルがあるはず)
$sudo python setup.py install

2. JPEGデコーダーのインストール
PILをインストールしても、JPEG画像を操作しようとすると次のエラーが発生する事がある。
IOError: decoder jpeg not available
このときは、JPEGデコーダーを追加でインストールする。

http://www.ijg.org/
jpegsrc.v7.tar.gzファイルをダウンロードして、展開する
Finder -> アプリケーション -> ユーティリティ -> ターミナル
$cd (展開したディレクトリ。install.txtがあるはず)
./configure
make
make test
sudo make install

このあと、1.をもう一度行う。
そのとき1.のディレクトリにあるbuildディレクトリを削除しておく
sudo rm -fr build

djangoテンプレートで日本語が文字化けする

utf-8で保存された文字列をsjisで定義されたdjangoのテンプレートで表示すると、日本語が化けます。
このときは、djangoのカスタムフィルターを用意して、utf-8をsjisに変換します。

[customfilters.py (utf-8 -> sjis変換をするフィルターを定義する)]
from google.appengine.ext import webapp

register = webapp.template.create_template_register()

@register.filter
def sjis(value):
return value.encode('sjis')

[main.py (テンプレートを出力するロジックのあるモジュール)]
webapp.template.register_template_library('customfilters')

[template.html]
{{ myValue|sjis }}


参考
http://kaihatsu.mikagamikobo.com/2009/09/google-app-engine-1.html

2009年10月8日木曜日

reportlabは1.2系では動かない

Google App EngineでPDFを出力するには、reportlabを使うとよいと書かれている。
しかしこのreportlab、ローカルのSDKではバージョンが1.2になると以下のエラーが発生する。

: 'HardenedModulesHook' object has no attribute '_files'

対応方法は、以下のURLから1.9をダウンロードしてアプリケーションに上書きすること。

「Google App Engine プロジェクト ホームページ」
http://code.google.com/p/googleappengine/downloads/list
※検索条件で「All donwloads」を選択する

ちなみに、本番環境ではSDKの環境に関係なくreportlabでPDFを生成できました。



1.2.7では動きました(^^)V

やっぱり駄目でした。具体的には、
1. ソースコードをlatin-1で保存して実行すると、実行できる。
2. ソースコードをutf-8で再保存して実行すると、上記のエラーが発生する
3. ソースコードをlatin-1にもどしても、やはりエラーが発生する
4. アプリケーションの.pycファイルを削除すると、実行できる(1.の状態に戻る)
です。
どうやら、pythonで鬼門のエンコード周りでどこかに不具合があるようです。
ちなみにサーバにデプロイするか、1.1.9にバージョンダウンするとうまく動くという事は、1.2.X系のGAEのSDKに問題がありそう...

2009年10月4日日曜日

静的ファイルを公開する

Google App Engineで言語がpythonのときに、静的なファイルを公開する方法。

1. 公開したいファイルを用意する。このときURLとファイル名は異なっていてもよい。
2. app.yamlのhandlersに次のエントリを用意する
- url: 静的ファイルをリクエストするURL
static_files: 用意した静的ファイルのパス
upload: 用意した静的ファイルのパス

例:http://foo.bar.com/hoge.htmlを公開する。

/static/hogeimpl.htmlファイルを用意する
- url: /hoge.html
static_files: static/hogeimpl.html
upload: static/hogeimpl.html

smtp2webがらみで使えるネタです。
この内容は、用途は違いますがGAEの一般的な質問に載っていました。
http://code.google.com/intl/ja/appengine/kb/general.html#erroruris

macのGAE Launcherでdebugログが出ない

Google App Engineのmac用環境で、ログ出力を実行してもdebugレベルのログが出力されない。

import logging

logging.info("これは出力される")
logging.debug("これは出力されない")

多分、サーバプロセス起動時にモードを変更する引数を渡せばよいのだと思うけど、macなのでそもそもコマンドラインの引数の渡し方がわかっていません。調査中です。

引数の渡し方がわかりました。
・Google App Engine Launcer上で、リストされているアプリケーションをダブルクリック
・"Extra flags"にフラグを追加
です。
参考URL:
http://blog.docuverse.com/2009/01/30/google-app-engine-launcher-options/

2009年10月3日土曜日

メールを送ろうとしてエラー

Google App Engineでメールを送ろうとしたら次のエラーが発生した

Traceback (most recent call last):
File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 509, in __call__
handler.post(*groups)
File "/base/data/home/apps/golfpaper/1.336764943207147696/main.py", line 83, in post
, body
File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 239, in send_mail
message.send(make_sync_call)
File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 714, in send
raise ERROR_MAP[e.application_error](e.error_detail)
InvalidSenderError: Unauthorized sender

原因を検索中...

メールを送信するときのアドレスが、アプリケーションに登録されている必要がある。
登録する方法は、
1. http://appengine.google.com/ を開き、対象となるアプリケーションをクリックする
2. Administration - Developersを選択する
3. メールアドレスを登録する
こんな感じでいけそうです。