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 }