spacer
spacer
開発者の談話室

携帯の最近のブログ記事

GoogleAnalyticsは携帯では利用できません。これは、Javascriptを使って計測サーバに画面表示情報を送信しているためです。

ですが、携帯からのアクセス時にサーバから直接HTTPリクエストを送信すれば、アクセス数を計測可能になります。しかし、この方法はアクセス数の多いサーバですと、サーバ負荷が増大するのであまりオススメできません。

秒間1000アクセス以上ある場合は、Googleへ携帯端末からアクセス情報を送るためのimgタグを自動生成する方法が望ましいです。

 <%= this.GetGoogleAnalyticsImageTag( "UA-0000-00", "your.domain.mobi" ); >
<script runat="server">
    /// <summary>
    ///
    /// </summary>
    /// <param name="utmac">登録番号 UA-XXXXX-XXXX</param>
    /// <param name="utmhn">ドメイン</param>
    public string GetGoogleAnalyticsImageTag( string utmac, string utmhn ) {
        Random rand = new Random( (int)DateTime.Now.Ticks );


        long win_time = DateTime.Now.ToFileTime();      // 現在時刻
        long unix_time = ( win_time - 116444735995904000 ) / 1000000;   // FileTimeからUnixTimeに変換
        string today = unix_time.ToString();
        string referer = "-";
        if( Request.UrlReferrer != null ) {
            referer = Request.UrlReferrer.AbsoluteUri;
        }
        string utmp = Request.Url.AbsoluteUri;

        string utmn = rand.Next( 1000000000, 2147483647 ).ToString();
        string cookie = Session.SessionID;
        string random = rand.Next( 1000000000, 2147483647 ).ToString();

        string uservar = "-";

        string useragent = "Unknown";
        if( Request.UserAgent != null ) {
            useragent = Request.UserAgent;
        }

        string requrl =
  "http://www.google-analytics.com/__utm.gif?" +
   "utmwv=1" +     // version
            "&utmn=" + utmn +  // 複数送信のブロック
            "&utmsr=-" +
   "&utmsc=-" +
   "&utmul=-" +
   "&utmje=0" +
   "&utmfl=-" +
   "&utmdt=-" +    // ページタイトル
            "&utmcs=-" +    // Character Encoding           
            "&utmhn=" + utmhn +
   "&utmr=" + referer +
   "&utmp=" + utmp +
   "&utmac=" + utmac +
   "&utmcc=__utma%3D" + cookie + // 端末識別
            "." + random + //
            "." + today + // 初回訪問時刻
            "." + today + // 前回訪問時刻
            "." + today + // 現在時刻
            ".2%3B%2B__utmb%3D" + cookie + // 下位互換性維持?
            "%3B%2B__utmc%3D" + cookie +  // 下位互換性維持?
            "%3B%2B__utmz%3D" + cookie +  // 下位互換性維持?
            "." + today +
   ".2.2.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B__utmv%3D" + cookie +
   "." + uservar + "%3B";  // user defined variable          

        return string.Format( @"<img src=""{0}"" width=""1"" height=""1"" />", requrl );
       
    }
   
</script>
 

イメージタグを出力するので、SSLページでは計測できません。SSLページでの計測は、やはりサーバから直接Googleの計測サーバにデータ送信するしかありません。

ASP.NET QRコード生成

|

標準の .Net Frameworkの中にQRコードを生成するライブラリがありません

最近ではWebサービスでQRコードを生成してくれるサービスもありますが、QRコードの生成機能などは外部サービスを使うよりも、自前のサーバで生成したほうがサーバの信頼性が高まります。

世にあるQRコード生成ライブラリをまとめてみました。いくつも製品・フリーソフトがあるので適切なものを選んでください。 

製品名 会社 価格・ライセンス形態 コメント
QRGen アジルテック 個人利用無料、商用利用には商用ライセンス15,000円 弊社のライブラリです。ご要望などありましたら連絡ください
QR_Encode スパイシーソフト フリーソフト、アプリ同梱の再配布OK。単体での再配布は禁止 基本機能のみ提供。出力QRコードのタイプが02に固定
BarCode.Net (有) パオ@オフィス 1ユーザライセンス18,900円。CompornentSourceだと18,480円。サーバライセンスは記述なし ソースコードを含めて購入することができる
ColorfulQRCodeMaker
DotNetBarcode
個人 再配布条件:本アプリの利用を明示すること。Webアプリについては「対応していない」と明記されているが、実際には利用できるが、Webで利用するとライセンス違反の可能性がある。著作者からWebでの利用ライセンスを確認する必要がある 色表現が多彩
ActiveReports
for .Net Professinal Edition
Data Dynamics 再配布ライセンス 294,000円 画像処理ライブラリの一環としてQRコード生成機能を提供している。高機能すぎる
LEADTOOLS 2D QR Code Barcode Modules Lead Technologies 再配布ライセンス147,000 + 210,000円 米国 995$。サーバライセンスは記述なし 高機能すぎてWeb利用には不向き

まとめ:

個人で利用するならばQRGenQR_Encodeがオススメです。Webアプリケーション用の商用ライセンスが必要な場合は、QRGenをご購入を検討ください。

先日、RFC違反のメールアドレスに関する記事を書きましたが、ASP.NETのライブラリはGlobal基準(またはMicrosoft基準)のため、ガラパゴス進化をしている日本のネット環境と乖離していることがあります。

System.Net.Mailはその中でも際立っていて、海外ではUTF-8 & Qエンコードが主流なため、国内のShift-JIS & Bエンコードという日本のネット環境に適合していません。

悩まれている方も多く、あちらこちらで記事があがっています。

System.Net.Mail問題その3(中の技術日誌)
せっかくsubjectとbodyにはエンコード方式の指定があるにもかかわらず、From, To, Cc, Bcc, ReplyToなどのこのMailAddressクラスにはエンコード方式を指定する方法がありません

結局、MailAddressクラスのコンストラクタが「送り先氏名 <user@address.com>」という文字列を解釈して処理してくれるにもかかわらず、Qエンコーディングなため、自前でBエンコード処理をして2つ変数をとるコンストラクタ MailAddress( address, displayname) を呼ぶ必要があります。

string from_name = MyBEncode( "株式会社 アジルテック", enc );
string from_address = "user@address.com"; 
msg.To.Add( new MailAddress( to_address, to_name ) );

また、Subject, Bodyのエンコードを指定できますが、iso-2022-jpに指定しても、

Subject: =?iso-2022-jp?Q?=1B$B%5%V%8%'%/%H=1B(B1?=
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 8bit

出力はSubjectはQエンコードされ、BodyのContent-Transfer-Encodingは8bitエンコーディングです。

結局、せっかく自動処理してくれるSubjectもMailMessage.SubjectEncodingは未指定にし、自前でBエンコーディングをする必要があります。

Bodyを7bitにするには、Content-Transfer-Encodingについては、msg.HeadersにAddしても追加されず、AlternateViewを使って7bitエンコーディングを実現する必要があります。

追加されない:
msg.Headers.Add( "Content-Transfer-Encoding", "7bit" );
AlternateViewを利用する:
byte[] buf = enc.GetBytes( body );
MemoryStream mem = new MemoryStream( buf );
AlternateView alt_msg = new AlternateView( mem, new ContentType("text/plain; charset=" + enc.BodyName ) ); 
alt_msg.TransferEncoding  = TransferEncoding.SevenBit;

これまでは上記の方法でも、「content-transfer-encoding: 7bit」と出力するところが、「content-transfer-encoding: sevenbit」となっていたため、正しく送信できなかったのですが、.Net Framework 2.0 SP1で、「[FIX] System.Net.Mime 名前空間または System.Net.Mail 名前空間を使用する Visual Studio 2005 プログラムを実行すると、TransferEncoding プロパティの値が正しくないことがある」修正が含まれたので、SP1以降は送信するこができます。

 参考:
 [.NET 2.0]日本語(ISO-2022-JP) を Content-Transfer-Encoding: 7bit で送信する方法

上記の方法で大部分は問題なく動作するが、まだ問題が残っています。RFC 2047に記述のあるエンコード行の76文字改行規制です。

encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
複数の行からなるヘッダフィールドの長さに制限はないが、1つ以上の
  'encoded-word' を含むそれぞれの行は、76文字に制限される。

改行いれた文字列を渡すと、MailMessageのSubjectプロパティもMailAddressクラスコンストラクタもエラーを発生します。

2バイト文字だと40文字越えるとこの制限に抵触します。

=?iso-2022-jp?B?GyRCJTUlViU4JSclLyVIRDkkJCU1JVYlOCUnJS8lSCRAJEgkSSQmJEokayRzJEckNyRnJCYkKyRKIzEjMiMzIzQjNSM2IzcjOCM5IzEjMiMzIzQjNSM2IzcjOCM5GyhCQUJDREVGRxskQiQiJCQkJiQoJCokKyQtJC8kMSQzJDUkNyQ5JDskPSQ/JEEkRCRGJEghIktcRnwkT0AyRTckSiRqGyhC?=

しかし、上記のような長いエンコード文字列を渡しても大丈夫なSMTPサーバ、メールクライアントも多いようです。Au, Softbankは76文字で区切らなくても表示できる端末があるので、少なくとも両社のSMTPサーバは受け取ります。(ただし、端末によっては表示されない可能性あり)

まとめ:

  1. ヘッダ中(To, Subject)のBエンコードは自分で行う。文字長は気にしなくてもよい
  2. 本文のエンコード指定はSP1を適用し、AlternateViewを用いる

RFCの作法は守りたいという方は、Socketから直接SMTPサーバと通信してください。

[追記 2008/11/20 ] 弊社より、サブジェクト文字化けとRFC非準拠アドレスに対応したSMTPClientを公開しました。現在、β公開につき無料で利用できます。ぜひお試しください。

RFC非準拠アドレスに対応メールライブラリ

問題:

System.Net.Mail.MailAddressクラスは携帯各社が許可している、RFCに準拠しないメールアドレスを渡すことができません。

MailAddress address = new MailAddress( "test...@docomo.ne.jp" );

上記のようなメールアドレスを渡そうとするとFormatExceptionが発生してしまいます。

System.FormatException はユーザー コードによってハンドルされませんでした。
  Message="指定された文字列は、電子メール アドレスに必要な形式ではありません。"
  Source="System"
  StackTrace:
       場所 System.Net.Mime.MailBnfHelper.ReadMailAddress(String data, Int32& offset, String& displayName)

原因:

System.Net.MailAddressがRFCで定められているよりも厳しくメールアドレスの形式をチェックしているため。

実はこのようなRFC準拠していないメールアドレスであっても「"test..."@docomo.ne.jp 」とアカウント部分をエスケープすることでRFC準拠として扱えるのですが、MailAddressクラスはFormatExceptionを発生させます。

解決方法:

ASP.NET開発で携帯メールアドレスを扱うことは多々あり、「RFC非準拠アドレスにメール送信できないのは仕様です」といっても発注元が検収してくれません。

そこで、簡単な逃げ道としては.Net Framework 1.1で使われていたSystem.Web.Mailを利用する方法があります。

MailMessage msg = new MailMessage();
msg.To = "test...@docomo.ne.jp";

MailMessageクラスのToプロパティはstring型でメール形式をチェックしません。どんな文字列でも渡すことができます。また、OSが日本語環境であれば、デフォルトのエンコーディングはiso-2022-jp かつ Bエンコードになるので、特に設定せずとも各携帯キャリア対応です。

いいことずくめに思えますが、下記のような問題点があります。

  1. 実行環境依存が発生する
  2. CDOモジュールが.Netプログラマにわかり難い
  3. HTMLメール送信機能が不十分
  4. SMTP/SSLが使えない

ひとつひとつ詳しく解説します。

1 実行環境依存が発生する

System.Web.Mailのメール送信はMicrosoft CDO for Exchange 2000のモジュールを利用しているため、実行環境によって挙動が変化します。本番環境でモジュールがなくて動かない・・・ということもありえます。

アプリケーションの実行アカウント権限がCDOオブジェクトにアクセスできないとアウトです。あちらこちらの掲示板で質問があがっては未解決という状態です。

特定のVersionのVisual Studioをインストールしたり、Exchange Serverをインストール&アンインストールしていると症状がでるといった報告もあります。

 参考:
 [MSDN] CDO.DLL ファイルが存在しない

2 CDOモジュールが.Netプログラマにわかり難い

この自由度の高かった1.1のSystem.Web.Mailが2.0でSystem.Net.Mailに置き換えられているのは、基本的にSystem.Web.MailはExchangeモジュールの.Net用ラッパークラスにすぎないためです。細かい制御は全て、CDOに対するメッセージを付加する必要があります。たとえば、portを25番以外に変更する場合には、MailMessageのFilesプロパティにCDOの設定をメッセージとして追加する必要があります。

msg.Fields[
"http://schemas.microsoft.com/cdo/configuration/smtpserverport"] = 25;

また、CDOのエラーメッセージが不親切で、原因の切り出しがし難い点があります。

 参考:
 「CDO.Message」を作成しなかったための」エラー メッセージのトラブルシューティング方法

3 HTMLメール送信機能が不十分

msg.BodyFormat = MailFormat.Html;

上記のプロパティを設定することでHTMLメールを送信することができるのですが、機能的に不十分です。携帯のデコメール等はimgタグで指定するsrc属性を外部リソースを指定することができません。そのため、添付ファイルを表示するためにContentIdを指定したいのですが、System.Web.Mail.MailAttachmentにはContentIdを指定できません。をまた、HTMLメールを指定した際の、Textメールは自動生成なので、HTMLとTextメールをそれぞれ整形して指定できません。

 参考:
 DoCoMo デコメ
 KDDI デコメ
 SoftBank

4 SMTP/SSLが使えない

SMTP/SSLをサポートしていないようです。CDOの設定を探せばあるのかしれませんが、ドキュメントを発掘できません。SMTPAuthはサポートしているのですが、平文 or NTLM(=CRAM-MD5 )となり、ベストエフォート設定はできません。ちなみにSMIME署名CAPICOMを使うのが常道なので、1.1、2.0いずれのVersionでもサポートしていません。

 参考:
 [Microsoft]System.Web.mail を使用している 有効 SMTP 認証の方法
 [MSDN] リファレンス http://schemas.microsoft.com/cdo/configuration/

総括:

入会案内程度のメールであればSystem.Web.Mailは利用に耐える」、セキュリティに執着しない顧客で、メルマガのようにHTMLメールが不要なケースであればSystem.Web.Mailでも十分です。しかし問題点1で指摘したように、テスト環境では動いてたものが、本番環境によってCDOモジュールが見つからないというエラーがでて顧客のクレームを浴びることもありえます。必ず、CDOモジュールが動作するかミニプログラムを本番サーバで動かして確認してください。

弊社ではSMTPは、System.Net.MailもSystem.Web.Mailのどちらも使うことを辞め、自前で実装したSMTPクライアントを利用しています。顧客からの要望に細かく対応できるので便利です。

 [追記 2008/11/20 ] 弊社より、サブジェクト文字化けとRFC非準拠アドレスに対応したSMTPClientを公開しました。現在、β公開につき無料で利用できます。ぜひお試しください。

RFC非準拠アドレスに対応メールライブラリ

問題:
 ASP.NETで携帯向けアプリケーションを作成すると、最近のAU端末ではinputタグに初期の入力文字を指定するための、formatやistyle属性が表示されません。

例:
ASPXファイルの記述
<asp:TextBox istyle="3" ID="TB_Mail" runat="server" />

原因:
 Up.BrowserのVersion6以降では、HTMLレンダリングにSystem.Web.UI.XhtmlTextWriterが用いられているため、istyleなどの非正則属性を除去してしまう。

対策:
 Html32TextWriterもしくはChtmlTextWriterを利用するように設定する。
VS2005以降で開発しているのでしたら、App_Browsersフォルダを追加して、KDDI AU用の定義ファイルを作成してください。

例: <browsers / / /> <browser refid="Up" / / /> <capabilities> <capability name="supportsInputIStyle" value="true" /> </capabilities> <controlAdapters markuptextwritertype="System.Web.UI.ChtmlTextWriter" /> </browser> </browsers>

デフォルト定義されている%Windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers\ 内部のopenwave.browserファイルの407行目を直接編集した場合は、コマンドプロンプトから「aspnet_regbrowsers.exe - i」を実行してください。

<controlAdapters markupTextWriterType="System.Web.UI.XhtmlTextWriter" />
↓変更
<controlAdapters markupTextWriterType="System.Web.UI.ChtmlTextWriter" />

参考情報: 

 MSDN ブラウザ定義ファイルのスキーマ

 



 
spacer
spacer