/*
* Aipo is a groupware program developed by TOWN, Inc.
* Copyright (C) 2004-2015 TOWN, Inc.
* http://www.aipo.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aimluck.eip.webmail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import com.aimluck.commons.field.ALNumberField;
import com.aimluck.commons.field.ALStringField;
import com.aimluck.commons.utils.ALStringUtil;
import com.aimluck.eip.cayenne.om.portlet.EipMMailAccount;
import com.aimluck.eip.common.ALAbstractFormData;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALEipManager;
import com.aimluck.eip.common.ALEipPost;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.fileupload.beans.FileuploadLiteBean;
import com.aimluck.eip.fileupload.util.FileuploadUtils;
import com.aimluck.eip.mail.ALFolder;
import com.aimluck.eip.mail.ALLocalMailMessage;
import com.aimluck.eip.mail.ALMailFactoryService;
import com.aimluck.eip.mail.ALMailHandler;
import com.aimluck.eip.mail.ALMailSenderContext;
import com.aimluck.eip.mail.ALSmtpMailContext;
import com.aimluck.eip.mail.ALSmtpMailSender;
import com.aimluck.eip.mail.util.ALMailUtils;
import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.services.portal.ALPortalApplicationService;
import com.aimluck.eip.services.storage.ALStorageService;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.util.ALLocalizationUtils;
import com.aimluck.eip.webmail.beans.WebmailAccountLiteBean;
import com.aimluck.eip.webmail.util.WebMailUtils;
/**
* Webメールフォームデータを管理するためのクラスです。 <br />
*/
public class WebMailFormData extends ALAbstractFormData {
private static final JetspeedLogger logger = JetspeedLogFactoryService
.getLogger(WebMailFormData.class.getName());
/** 件名の最大文字数 */
private final int FIELD_SUBJECT_MAX_LEN = 256;
/** 宛先(To,CC,BCC)の最大文字数 */
private final int FIELD_RECIPIENT_MAX_LEN = 512;
/** メール本文の最大文字数 */
private final int FIELD_BODY_MAX_LEN = 50000;
/** タイプ:デフォルトメール */
public static final int TYPE_DEF_MAIL = -1;
/** タイプ:新規メール */
public static final int TYPE_NEW_MAIL = 0;
/** タイプ:返信メール */
public static final int TYPE_REPLY_MAIL = 1;
/** タイプ:転送メール */
public static final int TYPE_FORWARD_MAIL = 2;
/** タイプ:全員に返信メール */
public static final int TYPE_REPLY_ALL_MAIL = 3;
/** メール作成のタイプ */
private ALNumberField mailType = null;
/** 宛名 */
private ALStringField to = null;
/** CC */
private ALStringField cc = null;
/** BCC */
private ALStringField bcc = null;
/** 件名 */
private ALStringField subject = null;
/** 本文 */
private ALStringField body = null;
/** 添付ファイルリスト */
private List<FileuploadLiteBean> fileuploadList = null;
private String folderName = null;
/** */
private int userId = -1;
/** */
private int accountId = -1;
/** メールアカウント一覧 */
private List<WebmailAccountLiteBean> mailAccountList = null;
private String orgId;
@Override
public void init(ALAction action, RunData rundata, Context context)
throws ALPageNotFoundException, ALDBErrorException {
super.init(action, rundata, context);
userId = ALEipUtils.getUserId(rundata);
try {
accountId =
Integer.parseInt(ALEipUtils.getTemp(
rundata,
context,
WebMailUtils.ACCOUNT_ID));
} catch (Exception e) {
accountId = 0;
}
folderName = rundata.getParameters().getString("folderName");
orgId = Database.getDomainName();
mailAccountList = WebMailUtils.getMailAccountList(rundata, context);
}
/**
*
*/
@Override
public void initField() {
// メール作成のタイプ
mailType = new ALNumberField();
mailType.setFieldName(ALLocalizationUtils
.getl10n("WEBMAIL_SETFIELDNAME_TYPE"));
// To
to = new ALStringField();
to.setFieldName(ALLocalizationUtils.getl10n("WEBMAIL_SETFIELDNAME_TO"));
to.setTrim(true);
// CC
cc = new ALStringField();
cc.setFieldName(ALLocalizationUtils.getl10n("WEBMAIL_SETFIELDNAME_CC"));
cc.setTrim(true);
// BCC
bcc = new ALStringField();
bcc.setFieldName(ALLocalizationUtils.getl10n("WEBMAIL_SETFIELDNAME_BCC"));
bcc.setTrim(true);
// Subject
subject = new ALStringField();
subject.setFieldName(ALLocalizationUtils
.getl10n("WEBMAIL_SETFIELDNAME_SUBJECT"));
subject.setTrim(true);
// Body
body = new ALStringField();
body.setFieldName(ALLocalizationUtils.getl10n("WEBMAIL_SETFIELDNAME_BODY"));
body.setTrim(false);
fileuploadList = new ArrayList<FileuploadLiteBean>();
}
/**
* 各フィールドに対する制約条件を設定する抽象メソッドです。
*/
@Override
protected void setValidator() {
// 宛先を必須項目にする
to.setNotNull(true);
to.limitMaxLength(FIELD_RECIPIENT_MAX_LEN);
// CC
cc.limitMaxLength(FIELD_RECIPIENT_MAX_LEN);
// BCC
bcc.limitMaxLength(FIELD_RECIPIENT_MAX_LEN);
// 件名の文字数制限
subject.limitMaxLength(FIELD_SUBJECT_MAX_LEN);
// 本文の文字数制限
body.limitMaxLength(FIELD_BODY_MAX_LEN);
}
/**
* フォームデータの妥当性を検証する.
*
* @param msgList
* エラーメッセージのリスト
*/
@Override
public boolean validate(List<String> msgList) {
String delim = ",;";
if (to.validate(msgList)
&& !WebMailUtils.checkAddress(to.getValue(), delim)) {
msgList.add("『 <span class='em'>宛先</span> 』を正しく入力してください。");
}
if (cc.validate(msgList)
&& cc.getValue().trim().length() > 0
&& !WebMailUtils.checkAddress(cc.getValue(), delim)) {
msgList.add("『 <span class='em'>CC</span> 』を正しく入力してください。");
}
if (bcc.validate(msgList)
&& bcc.getValue().trim().length() > 0
&& !WebMailUtils.checkAddress(bcc.getValue(), delim)) {
msgList.add("『 <span class='em'>BCC</span> 』を正しく入力してください。");
}
subject.validate(msgList);
body.validate(msgList);
return (msgList.size() == 0);
}
/**
*
* @param rundata
* @param context
* @param msgList
* @return
*/
@Override
protected boolean deleteFormData(RunData rundata, Context context,
List<String> msgList) {
try {
int index;
try {
index =
Integer.parseInt(ALEipUtils.getTemp(
rundata,
context,
ALEipConstants.ENTITY_ID));
} catch (Exception e) {
return false;
}
String currentTab = ALEipUtils.getTemp(rundata, context, "tab");
int type_mail =
(WebMailUtils.TAB_RECEIVE.equals(currentTab))
? ALFolder.TYPE_RECEIVE
: ALFolder.TYPE_SEND;
ALMailHandler handler =
ALMailFactoryService.getInstance().getMailHandler();
ALFolder folder =
handler.getALFolder(type_mail, orgId, userId, Integer
.valueOf(accountId));
folder.deleteMail(index);
} catch (Exception e) {
logger.error("webmail", e);
return false;
}
return true;
}
/**
*
* @param rundata
* @param context
* @param msgList
* @return
*/
@Override
protected boolean insertFormData(RunData rundata, Context context,
List<String> msgList) {
String[] attachmentFilepaths = null;
try {
FileuploadLiteBean filebean = null;
boolean hasAttachments =
(fileuploadList != null && fileuploadList.size() > 0);
if (hasAttachments) {
int size = fileuploadList.size();
attachmentFilepaths = new String[size];
for (int i = 0; i < size; i++) {
filebean = fileuploadList.get(i);
attachmentFilepaths[i] =
ALStorageService.getDocumentPath(
FileuploadUtils.FOLDER_TMP_FOR_ATTACHMENT_FILES,
userId + ALStorageService.separator() + folderName)
+ ALStorageService.separator()
+ filebean.getFileId();
}
}
// 件名の値を検証
if (subject.getValue() == null || subject.getValue().equals("")) {
subject.setValue("無題");
}
// 返信メールの場合は,ヘッダを追加する.
Map<String, String> map = null;
if (getMailType().getValue() == TYPE_REPLY_MAIL
|| getMailType().getValue() == TYPE_REPLY_ALL_MAIL) {
ALLocalMailMessage msg = null;
try {
msg =
(ALLocalMailMessage) WebMailUtils.getSelectedLocalMailMessage(
rundata,
context,
(int) getMailType().getValue());
if (msg == null) {
return false;
}
} catch (Exception e) {
return false;
}
String in_reply_tos = msg.getMessageID();
StringBuffer reference = new StringBuffer();
String[] references = msg.getHeader("References");
map = new LinkedHashMap<String, String>();
if (references != null && references.length > 0) {
reference.append(ALMailUtils.getOneString(references, " "));
}
if (in_reply_tos != null && (!in_reply_tos.equals(""))) {
map.put("In-Reply-To", in_reply_tos);
reference.append(" ").append(in_reply_tos);
}
map.put("References", reference.toString());
}
if (map != null && map.size() == 0) {
map = null;
}
String delim = ",;";
// オブジェクトモデルを取得
EipMMailAccount account = ALMailUtils.getMailAccount(userId, accountId);
ALMailHandler handler =
ALMailFactoryService.getInstance().getMailHandler();
// 送信サーバ情報
ALMailSenderContext scontext =
ALMailUtils.getALSmtpMailSenderContext(orgId, account);
// 送信メッセージのコンテキスト
ALSmtpMailContext mailcontext =
ALMailUtils.getALSmtpMailContext(ALMailUtils.getTokens(ALStringUtil
.unsanitizing(to.getValue()), delim), ALMailUtils.getTokens(
ALStringUtil.unsanitizing(cc.getValue()),
delim), ALMailUtils.getTokens(ALStringUtil.unsanitizing(bcc
.getValue()), delim), account.getMailAddress(), ALStringUtil
.unsanitizing(account.getMailUserName()), ALStringUtil
.unsanitizing(subject.getValue()), ALStringUtil.unsanitizing(body
.getValue()), attachmentFilepaths, map);
int success_send = handler.send(scontext, mailcontext);
if (success_send == ALSmtpMailSender.SEND_MSG_SUCCESS) {
if (hasAttachments) {
// 添付ファイル保存先のフォルダを削除
ALStorageService.deleteTmpFolder(userId, folderName);
}
} else {
if (success_send == ALSmtpMailSender.SEND_MSG_FAIL) {
msgList.add("メールを送信できませんでした。アカウント設定が間違っている可能性があります。");
} else if (success_send == ALSmtpMailSender.SEND_MSG_OVER_MAIL_MAX_SIZE) {
msgList.add(String.valueOf(FileuploadUtils.getMaxFileSize()).concat(
"MB を超えるサイズのメールは送信できません。"));
} else if (success_send == ALSmtpMailSender.SEND_MSG_FAIL_SMTP_AUTH) {
msgList.add("メールを送信できませんでした。SMTP認証の認証に失敗しました。");
}
return false;
}
} catch (Exception e) {
logger.error("webmail", e);
msgList.add("メールを送信できませんでした。アカウント設定が間違っている可能性があります。");
return false;
}
return true;
}
/**
*
* @param rundata
* @param context
* @param msgList
* @return
*/
@Override
protected boolean loadFormData(RunData rundata, Context context,
List<String> msgList) {
mailType.setValue(rundata.getParameters().getInt(
WebMailUtils.MAIL_TYPE,
TYPE_NEW_MAIL));
try {
ALLocalMailMessage msg =
(ALLocalMailMessage) WebMailUtils.getSelectedLocalMailMessage(
rundata,
context,
(int) getMailType().getValue());
if (msg == null) {
return false;
}
String tmpSubject = null;
if (getMailType().getValue() == TYPE_NEW_MAIL) {
// unreachable flow
// TO
Address[] tos = msg.getRecipients(Message.RecipientType.TO);
this.setTo(ALMailUtils.getAddressString(tos));
// CC
Address[] ccs = msg.getRecipients(Message.RecipientType.CC);
this.setCc(ALMailUtils.getAddressString(ccs));
// BCC
Address[] bccs = msg.getRecipients(Message.RecipientType.BCC);
this.setBcc(ALMailUtils.getAddressString(bccs));
tmpSubject = msg.getSubject();
} else if (getMailType().getValue() == TYPE_REPLY_MAIL) {
// TO
this.setTo(ALMailUtils.getFromDelegateExtract(msg));
tmpSubject = "Re: " + msg.getSubject();
} else if (getMailType().getValue() == TYPE_FORWARD_MAIL) {
tmpSubject = "Fwd: " + msg.getSubject();
} else if (getMailType().getValue() == TYPE_REPLY_ALL_MAIL) {
// TO
Address[] from = ALMailUtils.getFromDelegateExtractForAddress(msg);
Address[] to = msg.getRecipients(Message.RecipientType.TO, false);
EipMMailAccount myaccount =
ALMailUtils.getMailAccount(userId, accountId);
String myaddress = myaccount.getMailAddress();
List<Address> allList = new ArrayList<Address>();
allList.addAll(Arrays.asList(from));
allList.addAll(Arrays.asList(to));
List<Address> replayList = new ArrayList<Address>();
for (Address address : allList) {
if (address instanceof InternetAddress) {
InternetAddress internetAddress = (InternetAddress) address;
String email = internetAddress.getAddress();
if (email != null
&& !email.equalsIgnoreCase(myaddress)
&& !email.contains("<" + myaddress + ">")) {
replayList.add(address);
}
}
}
this.setTo(ALMailUtils.getAddressString(replayList
.toArray(new Address[replayList.size()])));
// CC
Address[] ccs = msg.getRecipients(Message.RecipientType.CC, false);
this.setCc(ALMailUtils.getAddressString(ccs));
// BCC
Address[] bccs = msg.getRecipients(Message.RecipientType.BCC);
this.setBcc(ALMailUtils.getAddressString(bccs));
tmpSubject = "Re: " + msg.getSubject();
}
// Subject
this.setSubject(tmpSubject);
// 返信の原文付与
String[] tmp2 = msg.getBodyTextArray();
StringBuffer replies = new StringBuffer();
replies.append("\r\n\r\n\r\n" + "------Original Message-------\r\n");
if (tmp2 != null) {
for (String factor : tmp2) {
replies.append("> " + factor + "\r\n");
}
}
// Body
try {
// オブジェクトモデルを取得
EipMMailAccount account = ALMailUtils.getMailAccount(userId, accountId);
// 署名と返信とを本文に追加
if (account.getSignature() != null
&& !"".equals(account.getSignature())) {
body.setValue(replies + "\r\n\r\n\r\n" + account.getSignature());
} else {
body.setValue(replies.toString());
}
} catch (Exception ex) {
logger.error("webmail", ex);
}
if (getMailType().getValue() == TYPE_FORWARD_MAIL) {
msg =
(ALLocalMailMessage) WebMailUtils.getSelectedLocalMailMessage(
rundata,
context,
TYPE_NEW_MAIL);
if (msg == null) {
return false;
}
String[] filenames = msg.getAttachmentFileNameArray();
if (filenames != null && filenames.length > 0) {
/** 添付ファイルを含んだメールを転送する */
if (folderName == null || folderName.equals("")) {
folderName = "undefined";
}
for (int i = 0; i < filenames.length; i++) {
/** 各々の添付ファイルを、一度ファイルに書き出して再度添付する */
int fileId = Long.valueOf(System.nanoTime()).intValue();
String newAttachmentFileName = String.valueOf(fileId);
String realfilename = filenames[i];
if (realfilename == null) {
continue;
}
ALStorageService.createNewTmpFile(
msg.getInputStream(i),
userId,
folderName,
newAttachmentFileName,
realfilename);
FileuploadLiteBean filebean = new FileuploadLiteBean();
filebean.initField();
filebean.setFileId(fileId);
filebean.setFileName(realfilename);
filebean.setFolderName(folderName);
fileuploadList.add(filebean);
}
}
}
return true;
} catch (Exception e) {
logger.error("webmail", e);
return false;
}
}
@Override
protected boolean updateFormData(RunData rundata, Context context,
List<String> msgList) throws ALPageNotFoundException, ALDBErrorException {
return false;
}
/**
*
* @param rundata
* @param context
* @param msgList
* @return
* @throws ALPageNotFoundException
* @throws ALDBErrorException
*/
@Override
protected boolean setFormData(RunData rundata, Context context,
List<String> msgList) throws ALPageNotFoundException, ALDBErrorException {
boolean res = super.setFormData(rundata, context, msgList);
if (accountId <= 0 || userId <= 0) {
return res;
}
try {
fileuploadList = FileuploadUtils.getFileuploadList(rundata);
// Body
// オブジェクトモデルを取得
EipMMailAccount account = ALMailUtils.getMailAccount(userId, accountId);
// 署名を本文に追加
if (!ALEipConstants.MODE_INSERT.equals(rundata.getParameters().get(
ALEipConstants.MODE))
&& account.getSignature() != null
&& !"".equals(account.getSignature())) {
StringBuffer bodybuf = new StringBuffer();
if (body.getValue() != null) {
bodybuf.append(body.getValue());
}
bodybuf.append("\r\n\r\n\r\n");
bodybuf.append(account.getSignature());
body.setValue(bodybuf.toString());
}
} catch (Exception ex) {
logger.error("webmail", ex);
}
return res;
}
/**
* @return
*/
public ALStringField getBcc() {
return bcc;
}
/**
* @return
*/
public ALStringField getBody() {
return body;
}
/**
* @return
*/
public ALStringField getCc() {
return cc;
}
/**
* @return
*/
public ALStringField getSubject() {
return subject;
}
/**
* @return
*/
public ALStringField getTo() {
return to;
}
/**
* @return
*/
public ALNumberField getMailType() {
return mailType;
}
public int getMaxFileSize() {
return FileuploadUtils.getMaxFileSize();
}
/**
* @param field
*/
public void setMailType(int field) {
mailType.setValue(field);
}
/**
* @param field
*/
public void setBcc(String string) {
bcc.setValue(string);
}
/**
* @param field
*/
public void setBody(String string) {
body.setValue(string);
}
/**
* @param field
*/
public void setCc(String string) {
cc.setValue(string);
}
/**
* @param field
*/
public void setSubject(String string) {
subject.setValue(string);
}
/**
* @param field
*/
public void setTo(String string) {
to.setValue(string);
}
public String getAccountName() {
return ALMailUtils.getAccountName(userId, accountId);
}
/**
*
* @return
*/
public Map<Integer, ALEipPost> getPostMap() {
return ALEipManager.getInstance().getPostMap();
}
public List<FileuploadLiteBean> getAttachmentFileNameList() {
return fileuploadList;
}
public boolean hasAuthorityAddressBook() {
return ALPortalApplicationService.isActive("AddressBook");
}
public String getFolderName() {
return folderName;
}
public int getAccountId() {
return accountId;
}
public String getAddrForCell(ALStringField addrs_filed) {
if (addrs_filed == null) {
return "";
}
String addrs = addrs_filed.getValue();
if (addrs == null || addrs.length() == 0) {
return "";
}
StringBuffer addrbuf = new StringBuffer();
int count = 0;
String token = null;
StringTokenizer st = new StringTokenizer(addrs, ",");
int size = st.countTokens();
for (int i = 0; i < size; i++) {
token = st.nextToken();
if (token.indexOf("<") == -1) {
addrbuf.append(token);
} else {
StringTokenizer tmp_st = new StringTokenizer(token, "<>");
if (tmp_st.countTokens() == 2) {
tmp_st.nextToken();
addrbuf.append(tmp_st.nextToken());
}
}
count = count + 1;
if (count < size) {
addrbuf.append(",");
}
}
return addrbuf.toString();
}
public boolean isExistsAccount() {
if (mailAccountList != null && mailAccountList.size() > 0) {
return true;
} else {
return false;
}
}
}