001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.mail;
017
018 import java.io.InputStream;
019 import java.io.OutputStream;
020 // import java.io.ByteArrayOutputStream;
021 import java.io.ByteArrayInputStream;
022 import java.io.UnsupportedEncodingException;
023 import java.io.IOException;
024
025 import javax.activation.DataHandler;
026 import javax.activation.DataSource;
027 import javax.mail.internet.InternetAddress;
028 import javax.mail.internet.MimeMessage;
029 import javax.mail.internet.MimeUtility;
030 import javax.mail.MessagingException;
031 import com.sun.mail.util.BASE64EncoderStream;
032
033 import java.nio.charset.Charset; // 5.5.2.6 (2012/05/25)
034
035 /**
036 * MailCharsetFactory は、MailCharset インターフェースを実è£?�—たサブクラスã‚?
037 * 作æ?する ファクトリクラスですã?
038 *
039 * 引数のキャラクタセãƒ?ƒˆ名が、Windows-31J 、MS932 の場合ã?ã€?
040 * 『1.Windows-31J + 8bit 送信ã€?の実è£?�§ある、Mail_Windows31J_Charset
041 * サブクラスを返しますã?
042 * それ以外がæŒ?®šされた場合ã?、ISO-2022-JP を使用して、ã??’.ISO-2022-JP に独自変換 + 7bit 送信ã€?
043 * の実è£?�§ある、Mail_ISO2022JP_Charset サブクラスを返しますã?
044 *
045 * @version 4.0
046 * @author Kazuhiko Hasegawa
047 * @since JDK5.0,
048 */
049 class MailCharsetFactory {
050
051 /**
052 * インスタンスの生æ?を抑止しますã?
053 */
054 private MailCharsetFactory() {
055 // 何もありませんã€?PMD エラー回避)
056 }
057
058 /**
059 * キャラクタセãƒ?ƒˆに応じたã?MailCharset オブジェクトを返しますã?
060 *
061 * Windows-31J 、MS932 、Shift_JIS の場合ã?、Mail_Windows31J_Charset
062 * そã?他ã?、ISO-2022-JP として、Mail_ISO2022JP_Charset を返しますã?
063 *
064 * 注意:null の場合ã?、デフォルトではなくã?Mail_ISO2022JP_Charset を返しますã?
065 *
066 * @param charset キャラクタセãƒ?ƒˆ[Windows-31J/MS932/Shift_JIS/そã?他]
067 *
068 * @return MailCharset
069 */
070 static MailCharset newInstance( final String charset ) {
071 final MailCharset mcset;
072
073 if( "MS932".equalsIgnoreCase( charset ) ||
074 "Shift_JIS".equalsIgnoreCase( charset ) ||
075 "Windows-31J".equalsIgnoreCase( charset ) ) {
076 mcset = new Mail_Windows31J_Charset( charset );
077 }
078 else {
079 mcset = new Mail_ISO2022JP_Charset();
080 }
081 return mcset ;
082 }
083
084 /**
085 * MailCharset インターフェースを実è£?�—ã�?Windwos-31J エンコード時のサブクラスですã?
086 *
087 * 『1.Windows-31J + 8bit 送信ã€?の実è£?�§すã?
088 *
089 * @version 4.0
090 * @author Kazuhiko Hasegawa
091 * @since JDK5.0,
092 */
093 static class Mail_Windows31J_Charset implements MailCharset {
094 private final String charset ; // "Windows-31J" or "MS932"
095
096 /**
097 * 引数に、エンコード方式をæŒ?®šして、作æ?するコンストラクタですã?
098 *
099 * @param charset String
100 */
101 public Mail_Windows31J_Charset( final String charset ) {
102 this.charset = charset;
103 }
104
105 /**
106 * ãƒ?‚ストをセãƒ?ƒˆしますã?
107 * Part#setText() の代わりにこちらを使ã�?‚ˆã�?�«しますã?
108 *
109 * ※ å†?ƒ¨で、MessagingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
110 *
111 * @param mimeMsg MimeMessage
112 * @param text String
113 */
114 public void setTextContent( final MimeMessage mimeMsg, final String text ) {
115 try {
116 mimeMsg.setText( text,charset ); // "text/plain" Content
117 }
118 catch( MessagingException ex ) {
119 String errMsg = "æŒ?®šã?ãƒ?‚ストをセãƒ?ƒˆできませんã€?
120 + "text=" + text + " , charset=" + charset ;
121 throw new RuntimeException( errMsg,ex );
122 }
123 }
124
125 /**
126 * 日本語を含ã‚??ãƒ?ƒ€用ãƒ?‚ストを生æ?しますã?
127 * 変換結果は ASCII なので、これをそã?まま setSubject ã‚?InternetAddress
128 * のパラメタとして使用してくださいã€?
129 *
130 * ※ å†?ƒ¨で、UnsupportedEncodingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
131 *
132 * @param text String
133 *
134 * @return 日本語を含ã‚??ãƒ?ƒ€用ãƒ?‚スãƒ?
135 */
136 public String encodeWord( final String text ) {
137 try {
138 return MimeUtility.encodeText( text, charset, "B" );
139 }
140 catch( UnsupportedEncodingException ex ) {
141 String errMsg = "æŒ?®šã?エンコードが出来ませんã€?
142 + "text=" + text + " , charset=" + charset ;
143 throw new RuntimeException( errMsg,ex );
144 }
145 }
146
147 /**
148 * 日本語を含ã‚?‚¢ドレスを生成しますã?
149 * personal に、日本語が含まれると想定してã�?�¾すã?
150 * サブクラスで、日本語å?ç�?‚’行う場合ã?方法ã?、それぞれ異なりますã?
151 *
152 * ※ å†?ƒ¨で、UnsupportedEncodingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
153 *
154 * @param address String
155 * @param personal String
156 *
157 * @return InternetAddress
158 */
159 public InternetAddress getAddress( final String address,final String personal ) {
160 try {
161 return new InternetAddress( address,personal,charset );
162 }
163 catch( UnsupportedEncodingException ex ) {
164 String errMsg = "æŒ?®šã?エンコードが出来ませんã€?
165 + "address=" + address + " , charset=" + charset ;
166 throw new RuntimeException( errMsg,ex );
167 }
168 }
169
170 /**
171 * Content-Transfer-Encoding を指定するå?合ã? ビット数を返しますã?
172 *
173 * Windows系はã€?bit / ISO-2022-JP 系はã€?bit になりますã?
174 *
175 * @return ビット数("8bit" 固å®?
176 */
177 public String getBit() {
178 return "8bit" ;
179 }
180 }
181
182 /**
183 * MailCharset インターフェースを実è£?�—ã�?ISO-2022-JP エンコード時のサブクラスですã?
184 *
185 * 『2.ISO-2022-JP に独自変換 + 7bit 送信ã€?の実è£?�§すã?
186 *
187 * @version 4.0
188 * @author Kazuhiko Hasegawa
189 * @since JDK5.0,
190 */
191 static class Mail_ISO2022JP_Charset implements MailCharset {
192
193 /**
194 * プラãƒ?ƒˆフォーãƒ?¾�存ã?ãƒ?ƒ•ォルトã? Charset ですã?
195 * プラãƒ?ƒˆフォーãƒ?¾�存æ?をè?慮する場合ã?エンコード指定で作æ?しておく事をお勧めしますã?
196 *
197 * @og.rev 5.5.2.6 (2012/05/25) findbugs対å¿?
198 */
199 private static final Charset DEFAULT_CHARSET = Charset.defaultCharset() ;
200
201 /**
202 * ãƒ?‚ストをセãƒ?ƒˆしますã?
203 * Part#setText() の代わりにこちらを使ã�?‚ˆã�?�«しますã?
204 *
205 * ※ å†?ƒ¨で、MessagingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
206 *
207 * @param mimeMsg MimeMessage
208 * @param text String
209 */
210 public void setTextContent( final MimeMessage mimeMsg, final String text ) {
211 try {
212 // mimeMsg.setText(text, "ISO-2022-JP");
213 mimeMsg.setDataHandler(new DataHandler(new JISDataSource(text)));
214 }
215 catch( MessagingException ex ) {
216 String errMsg = "æŒ?®šã?ãƒ?‚ストをセãƒ?ƒˆできませんã€?
217 + "text=" + text ;
218 throw new RuntimeException( errMsg,ex );
219 }
220 }
221
222 /**
223 * 日本語を含ã‚??ãƒ?ƒ€用ãƒ?‚ストを生æ?しますã?
224 * 変換結果は ASCII なので、これをそã?まま setSubject ã‚?InternetAddress
225 * のパラメタとして使用してくださいã€?
226 *
227 * ※ å†?ƒ¨で、UnsupportedEncodingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
228 *
229 * @param text String
230 *
231 * @return 日本語を含ã‚??ãƒ?ƒ€用ãƒ?‚スãƒ?
232 */
233 public String encodeWord( final String text ) {
234 try {
235 return "=?ISO-2022-JP?B?" +
236 new String(
237 BASE64EncoderStream.encode(
238 CharCodeConverter.sjisToJis(
239 UnicodeCorrecter.correctToCP932(text).getBytes("Windows-31J")
240 )
241 )
242 ,DEFAULT_CHARSET ) + "?="; // 5.5.2.6 (2012/05/25) findbugs対å¿?
243 }
244 catch( UnsupportedEncodingException ex ) {
245 String errMsg = "æŒ?®šã?エンコードが出来ませんã€?
246 + "text=" + text + " , charset=Windows-31J" ;
247 throw new RuntimeException( errMsg,ex );
248 }
249 }
250
251 /**
252 * 日本語を含ã‚?‚¢ドレスを生成しますã?
253 * personal に、日本語が含まれると想定してã�?�¾すã?
254 * サブクラスで、日本語å?ç�?‚’行う場合ã?方法ã?、それぞれ異なりますã?
255 *
256 * ※ å†?ƒ¨で、UnsupportedEncodingException が発生したå?合ã?、RuntimeException に変換されて throw されますã?
257 *
258 * @param address String
259 * @param personal String
260 *
261 * @return InternetAddress
262 */
263 public InternetAddress getAddress( final String address,final String personal ) {
264 try {
265 return new InternetAddress( address,encodeWord( personal ) );
266 }
267 catch( UnsupportedEncodingException ex ) {
268 String errMsg = "æŒ?®šã?エンコードが出来ませんã€?
269 + "address=" + address ;
270 throw new RuntimeException( errMsg,ex );
271 }
272 }
273
274 /**
275 * Content-Transfer-Encoding を指定するå?合ã? ビット数を返しますã?
276 *
277 * Windows系はã€?bit / ISO-2022-JP 系はã€?bit になりますã?
278 *
279 * @return ビット数("7bit" 固å®?
280 */
281 public String getBit() {
282 return "7bit" ;
283 }
284 }
285
286 /**
287 * ãƒ?‚ストã?本æ–?‚’送信するための DataSource ですã?
288 *
289 * Windows-31J でバイトコードに変換した後ã?独自エンコードにてã€?
290 * Shift-JIS â‡?JIS 変換してã�?�¾すã?
291 *
292 * @version 4.0
293 * @author Kazuhiko Hasegawa
294 * @since JDK5.0,
295 */
296 static class JISDataSource implements DataSource {
297 private final byte[] data;
298
299 public JISDataSource( final String str ) {
300 try {
301 data = CharCodeConverter.sjisToJis(
302 UnicodeCorrecter.correctToCP932(str).getBytes("Windows-31J"));
303
304 } catch (UnsupportedEncodingException e) {
305 String errMsg = "Windows-31J でのエンコーãƒ?‚£ングがå?来ませんã€? + str;
306 throw new RuntimeException( errMsg,e );
307 }
308 }
309
310 /**
311 * ãƒ??タの MIME タイプをæ–?—å?の形で返しますã?
312 * かならず有効なタイプを返すべきですã?
313 * DataSource の実è£?�Œãƒ??タタイプを 決定できなã�??合ã?ã€?
314 * getContentType は "application/octet-stream" を返すことã‚?提案しますã?
315 *
316 * @return MIME タイãƒ?
317 */
318 public String getContentType() {
319 return "text/plain; charset=ISO-2022-JP";
320 }
321
322 /**
323 * ãƒ??タを表ã�?InputStream を返しますã?
324 * それができなã�??合ã?適åˆ?�ª例外をスローしますã?
325 *
326 * @return InputStream
327 * @throws IOException ※ こã?メソãƒ?ƒ‰からは、IOException は throw されませんã€?
328 */
329 public InputStream getInputStream() throws IOException {
330 return new ByteArrayInputStream( data );
331 }
332
333 /**
334 * ãƒ??タが書込可能なã‚?OutputStream を返しますã?
335 * それができなã�??合ã?適åˆ?�ª例外をスローしますã?
336 *
337 * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
338 *
339 * @return OutputStream
340 * @throws IOException ※ こã?メソãƒ?ƒ‰を実行すると、å¿?�š throw されますã?
341 */
342 public OutputStream getOutputStream() throws IOException {
343 String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
344 // throw new UnsupportedOperationException( errMsg );
345 throw new IOException( errMsg );
346 }
347
348 /**
349 * こã?オブジェクトã? '名前' を返しますã?
350 * こã?名前は下層のオブジェクトã?性質によりますã?
351 * ファイルをカプセル化すã‚?DataSource なã‚?オブジェクトã?
352 * ファイル名を返すようにするかもしれませんã€?
353 *
354 * @return オブジェクトã?名前
355 */
356 public String getName() {
357 return "JISDataSource";
358 }
359 }
360 }