Comments
Description
Transcript
JavaMailについての記事では
//from the vault / Java EEでJavaMailを使う メールを送れるWebアプリケーションの作成 T. LAMINE BA 本 必要なソフトウェア ケーションには、3 つの Web ページが含まれます。それぞれトップ・ページ、 「送 Windows 7)、Java EE 6 以降の JDK、IDE(本記事では NetBeans 7)、GlassFish 信完了」の確認ページ、 「送信失敗」の通知ページです。 や Apache Tomcat などの Web サーバーを使用します。 記事では、コア JavaMail API を利用して電子メールを送信する、シンプル な Web アプリケーションを作成する方法について説明します。このアプリ Web アプリケーションのトップ・ページ(図 1 参照)には、送信者と受信者の このチュートリアルでは、ソフトウェアとして Microsoft Windows(本記事では 電子メール・アドレスの入力フィールド、件名と本文の入力フィールド、SMTP サー バーに関連するいくつかのフィールド(IP アドレス、ユーザー名、パスワード、ポー ト番号)という Web コンポーネントが含まれています。もちろん、重要な「送信」 ボタンもあります。 確認ページ (図 2 参照)とそれに似た送信成功通知ページには、ユーザーがトッ プ・ページに戻るためのボタンのみが必要です。 JavaMail API JavaMail API は、電子メッセージの読取り、作成、送信などの一般的な電子メー ル機能を提供するパッケージです。JavaMail はプラットフォーム非依存、プロト コル非依存のフレームワークであり、Java EE に含まれています。 図 3 に示すとおり、JavaMail には、アプリケーション・コンポーネントが電子メー ルの送受信に使用する、アプリケーション・レベルのインタフェースがあります。 また、プロトコル固有の処理に対応するサービス・プロバイダ(SP)インタフェー スもあります。たとえば、SMTP は電子メールの送信に使用されるプロトコルです。 Post Office Protocol 3(POP3)は、電子メール受信用プロトコルの標準になって 図1:電子メール・アプリのメイン・ページ います。Internet Message Access Protocol(IMAP)は、POP3 の代わりに使用 できます。 さらに、JavaMail API には JavaBeans Activation Framework(JAF)が含まれ ており、Multipurpose Internet Mail Extensions(MIME)、URL、添付ファイルな ど、プレーンなテキスト以外の電子メール・コンテンツを扱えます。 図2:確認ページ ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 25 //from the vault / POP3 mail store SMTP Server なるgetterメソッドとsetterメソッドを作成します。受信者の電子メール・ア ドレスがString型のtoという変数だとすると、getterメソッドとsetterメソッ ドの定義方法はリスト1のようになります。 IMAP mail store JavaMail POP3 SP SMTP SP package useJavaMail; /*** すべての必要なライブラリのインポート ***/ IMAP SP JavaMail API リスト1: JAF Java Application 図3: JavaMail APIの設計 方法 @ManagedBean @RequestScoped public class emailJSFManagedBean { private String to; /** emailJSFManagedBeanの新しいインスタンスの作成 */ public emailJSFManagedBean() { to = null; } このチュートリアルではJavaServer Faces(JSF)テクノロジーを利用して Webアプリケーションを作成します。そのため、次のワークフローで進める ことにします。 1. バッキングBeanを作成する 2. コンポーネント・タグを使用してWebページを作成する 3. FacesServletインスタンスをマッピングする 手順1:バッキングBeanを作成する バッキングBeanは、JSFテクノロジー固有のマネージドBeanの一種で す。Webアプリケーションのロジックを格納しており、Webページに含まれ るWebコンポーネントとやり取りします。バッキングBeanには、それぞれの Webコンポーネントに対応するprivate属性、その属性に対応するgetterメソ ッドとsetterメソッド、さらに次の4つのタスクを処理するメソッドを含める ことができます。 ■■ Webページ間のナビゲーションに関連する処理を実行する ■■ アクション・イベントを処理する ■■ コンポーネントの値を検証する ■■ 値変更イベントを処理する これに従い、emailJSFManagedBeanというバッキングBeanの中に、本 記事の最初の方に記載した8つのWebコンポーネントのそれぞれに必要と ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 public String getTo() { return to; } public void setTo(String to) { this.to = to; } } このコードの @ManagedBeanは、バッキングBeanをリソースとしてJSF 実装に登録するための宣言です。また、@RequestScopedは、このマネー ジドBeanがリクエストのスコープでのみリソースとして存在することを示す アノテーションです。つまり、このBeanは、ユーザーがWebアプリケーション とやり取りするための1回のHTTPリクエストの期間だけ存在します。 このバッキングBeanでは、さらに2つのメソッドを作成します。. 1つ目のメソッドの役割は、ユーザーがWebアプリケーションで送信した すべての電子メールを検証することです(リスト2参照)。 26 //from the vault / リスト2: public void validateEmail(FacesContext context, UIComponent toValidate, Object value) { String message = ""; String email = (String) value; if(email == null ¦¦ email.equals("")) { ((UIInput)toValidate).setValid(false); message = "E-mail address is required"; context.addMessage( toValidate.getClientId(context), new FacesMessage(message)); } else if (!(email.contains("@") && email.contains("."))) { ((UIInput)toValidate).setValid(false); message = "E-mail address is invalid"; context.addMessage( toValidate.getClientId(context), new FacesMessage(message)); } } この電子メール検証メソッドは、次の3つの引数をとります。 ■■ JSF実装のコンテキスト :マネージドBeanからユーザー・インタフェースに エラー・メッセージを渡すためのものです。 ■■ このメソッドを呼び出すWebコンポーネントの識別子である UIComponent toValidate:この例でのWebコンポーネントは、ユー ザー入力を引数として受け取るテキスト入力フィールドのメソッドです(リ スト1参照)。ユーザー入力については図1を参照してください。 ■■ value変数:検証する必要のある電子メール・ アドレスを格納します。 したがって、リスト2に示すコードは、次のタスクを実行します。 ■■ Webコンポーネントのローカル値を取得する ■■ 値がnullや空であるかどうかをチェックする ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 値がnullまたは空の場合は、コンポーネントのvalidプロパティの値を falseに設定し、エラー・メッセージを「E-mail address is required」 に設定する ■■ そうでない場合は、 「@」とピリオド(「.」)が値に含まれているかどうか をチェックする ■■ 含まれていない場合は、 コンポーネントのvalidプロパティの値を falseに設定し、エラー・メッセージを「E-mail address is invalid」に 設定する エラー・メッセージは、FacesContextインスタンスに送られ、それによって 呼出し元のWebコンポーネントに関連付けられます。 2つ目のメソッドは、JavaMailを利用して電子メールを送信するロジック を扱います。このナビゲーション処理メソッドは、 「SEND E-MAIL」ボタンの クリックというアクションによってトリガーされます(リスト3参照)。 ■■ リスト3: public String submitEmail() { // 電子メールの作成と送信 /*** 変数の初期化 ***/ props = new Properties(); // propsにセッションとメッセージ・データを設定 session = Session.getDefaultInstance( props, null); message = new MimeMessage(session); try { message.setContent(this.getDescr(), "text/plain"); message.setSubject(this.getSubject()); fromAddress = new InternetAddress(this.getFrom()); message.setFrom(fromAddress); toAddress = new InternetAddress(this.getTo()); message.setRecipient(RecipientType.TO, toAddress); // メッセージの転送 27 //from the vault / message.saveChanges(); //送信のためには保存が必要 Transport transport = session.getTransport("smtp"); transport.connect(this.smtp, this.port, this.username, this.password); if(transport.isConnected() == false) return "b_response"; transport.sendMessage( message, message.getAllRecipients()); transport.close(); } catch (MessagingException me) { // 例外処理 return "b_response"; } return "g_response"; } このようなタイプのメソッドを、アクション・メソッドといいます。このメソッ ドは、引数をとらないpublicメソッドであり、Webアプリケーションで移動 先となるページを表す文字列を返します。この例では、このメソッドで電子 メールを生成して送信します。電子メールの送信が成功した場合、このメソ ッドはg_response(「good response」の略)を返し、その結果、ブラウ ザでg_response.xhtmlページが表示されます(図2参照)。電子メールの 送信が失敗した場合は、b_response(「bad response」の略)を返し、 ブラウザではb_response.xhtmlページが表示されます。. JavaMailを利用して電子メールを送信するためには、まずSessionク ラスの電子メール・セッション・インスタンスを初期化します。この電 子メール・セッションがJavaMailの起点となります。このメソッドで は、java.util.Propertiesクラスを使用して、電子メール・サーバー、ユーザ ー名、パスワードなどの情報を取得します。これらの情報は、アプリケーシ ョン全体で共有できます。この例では、次のようにして、Sessionクラスの デフォルト・インスタンスを作成します。 ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 session = Session.getDefaultInstance(props, null); 次に、作成したセッションを用いて、Messageクラスの電子メールを生成 します。ただし、Messageは抽象クラスであるため、代わりにサブクラスの MimeMessageを使用します。このクラスのメッセージでは、さまざまな 標準を規定したRFCで定義されているMIMEタイプとヘッダーを利用できま す。次のように、 セッションを引数としてメッセージを作成します。 MimeMessage message = new MimeMessage(session) 電子メールを送信するためには、Transport型のオブジェクトを操作しま す。メッセージは、SMTP転送プロトコルを使用して送信します。Transport クラスが送信を処理します。次のようにしてオブジェクトをインスタンス化 します。 Transport transport = session.getTransport("smtp"); このトランスポート・オブジェクトが、指定された認証情報(SMTPサーバー のアドレス、SMTP接続を受け付けるポート番号、ユーザー名、パスワード) を使用し、SMTPサーバーへの接続を試みます。 transport.connect(this.smtp, this.port, this.username, this.password); SMTPサーバーが接続を許可したら、sendコマンドを用いて電子メールが 送信されます。 最後に、closeコマンドを呼び出して、トランスポート・サービスをクロー ズします。 transport. sendMessage(message, message.getAllRecipients()); transport.close(); 28 //from the vault / NこのバッキングBeanを含むファイルは、WebアプリケーションのSources Packagesディレクトリの下に配置する必要がある点に注意してください。 手順2:コンポーネント・タグを使用してWebページを作成 する このアプリケーションのそれぞれのWebページでは、Facelets宣言言語を 活用することで、さまざまなWebコンポーネントのためのタグを生成しま す。 トップ・ページを作成します。このページ(図1参照)では、Web コンポーネントに関連するタグとして、inputText、inputSecre t、inputTextArea,、commandButtonの4種類を使用します。 inputTextは、HTMLでtypeがtextであるinputタグに相当します。つまり、 これもユーザー入力を受け付けるフィールドです。この例では、送信者の アドレス、受信者のアドレス、電子メールの件名、SMTPサーバーのアドレ ス、SMTPサーバーのユーザー名、SMTPサーバーのポート番号を取得するた めに、このタグを利用します。 inputSecretは、HTMLでpasswordであるinputタグに相当します。こ れもユーザー入力を受け付けるフィールドです。ただし、inputSecretは、 inputTextタグとは異なり、ユーザーが入力した値を表示しません。SMTP サーバーのパスワードを取得するために、このタグを使用します。 inputTextAreaは、HTMLのtextareaタグに相当します。送信する電子 メールの本文を取得するために、このタグを使用します。 このアプリケーションでは、標準バリデータを利用するか、バッキング Beanに実装した検証メソッドを呼び出して、ユーザー入力を検証します(リ スト2参照)。 たとえば、リスト4に示すコードを使用した「FROM」アドレス・フィールド では、Faceletsを利用してemailJSFManagedBean.validateEmail検証 メソッドを呼び出します。 リスト4: <h:form> <table> <tr> <th style="width:100px" align="right">FROM:</th> ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 <td> <h:inputText id="from" size="100" validator= "#{emailJSFManagedBean.validateEmail}" value="#{emailJSFManagedBean.from}" /> <span style="margin-left:10px"> <h:message style="color:red" for="from"/> </span> </td> </tr> </table> </form> なお、messageタグ(<h:message/>)の目的は、電子メール・アドレスが 検証されなかったときにエラー・メッセージを表示することです。 別の例として、 「SUBJECT」フィールドでは、リスト5に示すように、Facelets の標準バリデータを利用しています。 リスト5: <h:form> <table> <tr> <th style="width:100px" align="right">FROM:</th> <td> <h:inputText id="subject" size="100" validatorMessage="Subject is required" value="#{emailJSFManagedBean.subject}"> <f:validateRequired for="subject"/> </h:inputText> <span style="margin-left:10px"> <h:message style="color:red" for="from"/> </span> </td> </tr> </table> </form> 29 //from the vault / idがsubjectであるinputTextに対してvalidateRequired タグ (<f:validateRequired/>)を適用しています。これにより、 「SUBJECT」 </servlet-mapping> フィールドが空で、フォームが送信された場合、フォームが無効になります。 この例では、messageタグ(<h:message/>)がある場所にエラー・メッセ ージが表示されます。 なお、NetBeansなどのIDEを使用していれば、このマッピングは自動的に行 われます。 今回の例では、JavaMail APIの基本的な機能の使用方法のみを紹介 しました。しかし、このライブラリはさまざまな拡張が可能で、メール・ エージェントに関するほぼすべてのニーズに対応できるようになっていま す。JavaMailはJava EEで使用するために設計されたものですが、Java SEで も使うことができます。JavaMailによってプロジェクトがもっと楽しくなるこ とでしょう。 確認ページとエラー通知ページを作成します。T確認ペ ージ(g_response.xhtml)は、電子メールが送信されたときに呼び出 されます(図2参照)。一方、エラー通知ページ(b_response.xhtml) は、電子メールが送信できなかった場合に呼び出されます。いずれ のページでも、FaceletsによるWebコンポーネントは、次のような commandButton タグがそれぞれに1つだけ含まれます。 <h:form> <h:commandButton id="back" value="Back" action="index"> </h:form> 【編集注://from the vault /シリーズの記事は、過去のJava Magazine に掲載された記事を更新したもので、本記事もそれに該当します。本記事 は、2012年3月/4月号に初めて掲載されました】</article> T. Lamine Ba:Real Basisの社長で、西アフリカのJavaユーザー・ グループSeneJUGの共同設立者。JUG-Africaの初期メンバーの1 人。 このコードが生成するボタンをユーザーがクリックすると、トップ・ページ (index.xhtml)に戻ります。 手順3:FacesServletインスタンスをマッピングする 最後の手順として、Webデプロイメント・ディスクリプタであるweb.xmlファ イルを編集し、FacesServletインスタンスをマッピングします。リスト6に 一般的な例を示します。 リスト6: <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class> javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 30