Java tutorial
/* * webtop-mail is a WebTop Service developed by Sonicle S.r.l. * Copyright (C) 2014 Sonicle S.r.l. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY SONICLE, SONICLE DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * 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 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 or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Sonicle S.r.l. at email address sonicle@sonicle.com * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Sonicle WebTop" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Sonicle WebTop". */ package com.sonicle.webtop.mail; import com.sonicle.mail.sieve.SieveScriptBuilder; import com.fluffypeople.managesieve.ManageSieveClient; import com.fluffypeople.managesieve.SieveScript; import com.sonicle.commons.EnumUtils; import com.sonicle.commons.LangUtils; import com.sonicle.commons.LangUtils.CollectionChangeSet; import com.sonicle.commons.PathUtils; import com.sonicle.commons.db.DbUtils; import com.sonicle.commons.time.DateTimeUtils; import com.sonicle.webtop.core.CoreManager; import com.sonicle.webtop.core.app.WT; import com.sonicle.webtop.core.bol.OShare; import com.sonicle.webtop.core.model.IncomingShareRoot; import com.sonicle.webtop.core.model.SharePermsFolder; import com.sonicle.webtop.core.dal.DAOException; import com.sonicle.webtop.core.sdk.BaseManager; import com.sonicle.webtop.core.sdk.UserProfile.Data; import com.sonicle.webtop.core.sdk.UserProfileId; import com.sonicle.webtop.core.sdk.WTException; import com.sonicle.webtop.mail.bol.OAutoResponder; import com.sonicle.webtop.mail.bol.OIdentity; import com.sonicle.webtop.mail.bol.OInFilter; import com.sonicle.webtop.mail.bol.model.Identity; import com.sonicle.webtop.mail.dal.AutoResponderDAO; import com.sonicle.webtop.mail.dal.IdentityDAO; import com.sonicle.webtop.mail.dal.InFilterDAO; import com.sonicle.webtop.mail.model.AutoResponder; import com.sonicle.webtop.mail.model.MailFilter; import com.sonicle.webtop.mail.model.MailFiltersType; import com.sonicle.mail.sieve.SieveMatch; import com.sonicle.webtop.core.app.RunContext; import com.sonicle.webtop.core.app.SessionContext; import com.sonicle.webtop.core.app.WebTopSession; import com.sonicle.webtop.core.sdk.AuthException; import com.sonicle.webtop.core.sdk.UserProfile; import com.sonicle.webtop.core.util.IdentifierUtils; import com.sonicle.webtop.mail.bol.OExternalAccount; import com.sonicle.webtop.mail.bol.OTag; import com.sonicle.webtop.mail.dal.ExternalAccountDAO; import com.sonicle.webtop.mail.dal.TagDAO; import com.sonicle.webtop.mail.model.ExternalAccount; import com.sonicle.webtop.mail.model.SieveActionList; import com.sonicle.webtop.mail.model.SieveRuleList; import com.sonicle.webtop.mail.model.Tag; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.function.Function; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMultipart; import javax.mail.search.SearchTerm; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.joda.time.format.DateTimeFormatter; import org.jooq.exception.DataAccessException; import org.slf4j.Logger; /** * * @author gabriele.bulfon */ public class MailManager extends BaseManager implements IMailManager { public static final Logger logger = WT.getLogger(MailManager.class); public static final String IDENTITY_SHARING_GROUPNAME = "IDENTITY"; public static final String IDENTITY_SHARING_ID = "0"; public static final String SIEVE_OLD_WEBTOP_SCRIPT = "webtop"; public static final String SIEVE_WEBTOP_SCRIPT = "webtop5"; private SieveConfig sieveConfig = null; List<Identity> identities = null; public MailManager(boolean fastInit, UserProfileId targetProfileId) { super(fastInit, targetProfileId); } public void setSieveConfiguration(String host, int port, String username, String password) { //TODO: portare i parametri (host,port,user,pass) nel manager this.sieveConfig = new SieveConfig(host, port, username, password); } @Override public boolean sendMessage(InternetAddress from, Collection<InternetAddress> to, Collection<InternetAddress> cc, Collection<InternetAddress> bcc, String subject, MimeMultipart part) throws WTException { com.sonicle.webtop.mail.Service mail = findMailService(); return mail.sendMsg(from, to, cc, bcc, subject, part); } public com.sonicle.webtop.mail.Service findMailService() throws WTException { WebTopSession wts = SessionContext.getCurrent(); if (wts == null) throw new WTException("Unable to get session"); com.sonicle.webtop.mail.Service mail = (com.sonicle.webtop.mail.Service) wts .getPrivateServiceById(SERVICE_ID); if (mail == null) throw new WTException("Unable to get service"); return mail; } public InputStream getAttachmentInputStream(String accountId, String foldername, long uidmessage, int idattach) throws WTException { try { Service s = findMailService(); return s.getAttachmentInputStream(accountId, foldername, uidmessage, idattach); } catch (Exception exc) { throw new WTException(exc); } } public List<Identity> listIdentities() throws WTException { if (identities == null) identities = buildIdentities(); return identities; } public Identity getMainIdentity() { if (identities == null) { try { identities = buildIdentities(); } catch (WTException exc) { } } return identities.get(0); } public Identity addIdentity(Identity ident) throws WTException { Connection con = null; Identity newident = null; try { UserProfileId pid = getTargetProfileId(); con = WT.getConnection(SERVICE_ID); IdentityDAO idao = IdentityDAO.getInstance(); OIdentity oident = new OIdentity(); oident.setIdentityId(idao.getSequence(con).intValue()); oident.setIdentityUid(IdentifierUtils.getUUIDTimeBased()); oident.setDisplayName(ident.getDisplayName()); oident.setDomainId(pid.getDomainId()); oident.setEmail(ident.getEmail()); oident.setFax(ident.isFax()); oident.setMainFolder(ident.getMainFolder()); oident.setUserId(pid.getUserId()); idao.insert(con, oident); if (identities != null) { newident = new Identity(oident); identities.add(newident); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } return newident; } public void deleteIdentity(Identity ident) throws WTException { Connection con = null; try { con = WT.getConnection(SERVICE_ID); IdentityDAO idao = IdentityDAO.getInstance(); idao.deleteById(con, ident.getIdentityId()); if (identities != null) { Identity dident = findIdentity(ident.getIdentityId()); identities.remove(dident); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public Identity updateIdentity(int identityId, Identity ident) throws WTException { Connection con = null; Identity uident = null; try { UserProfileId pid = getTargetProfileId(); con = WT.getConnection(SERVICE_ID); IdentityDAO idao = IdentityDAO.getInstance(); OIdentity oident = new OIdentity(); oident.setDisplayName(ident.getDisplayName()); oident.setDomainId(pid.getDomainId()); oident.setEmail(ident.getEmail()); oident.setFax(ident.isFax()); oident.setMainFolder(ident.getMainFolder()); oident.setUserId(pid.getUserId()); if (ident.getIdentityUid() == null) ident.setIdentityUid(IdentifierUtils.getUUIDTimeBased()); oident.setIdentityUid(ident.getIdentityUid()); idao.update(con, identityId, oident); if (identities != null) { uident = findIdentity(ident.getIdentityId()); uident.setIdentityUid(ident.getIdentityUid()); uident.setDisplayName(ident.getDisplayName()); uident.setEmail(ident.getEmail()); uident.setFax(ident.isFax()); uident.setMainFolder(ident.getMainFolder()); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } return uident; } public Identity findIdentity(int id) { for (Identity ident : identities) { if (ident.getIdentityId() == id) return ident; } return null; } private List<Identity> buildIdentities() throws WTException { Connection con = null; List<Identity> idents = new ArrayList(); try { UserProfileId pid = getTargetProfileId(); //first add main identity Data udata = WT.getUserData(pid); Identity id = new Identity(0, null, udata.getDisplayName(), udata.getEmail().getAddress(), null); id.setIsMainIdentity(true); idents.add(id); //add configured additional identities con = WT.getConnection(SERVICE_ID); IdentityDAO idao = IdentityDAO.getInstance(); List<OIdentity> items = idao.selectByDomainUser(con, pid.getDomainId(), pid.getUserId()); for (OIdentity oi : items) { Identity ident = new Identity(oi); idents.add(ident); } //add automatic shared identities int autoid = -1; CoreManager core = WT.getCoreManager(getTargetProfileId()); for (IncomingShareRoot share : core.listIncomingShareRoots(SERVICE_ID, IDENTITY_SHARING_GROUPNAME)) { UserProfileId opid = share.getOriginPid(); udata = WT.getUserData(opid); List<OShare> folders = core.listIncomingShareFolders(share.getShareId(), IDENTITY_SHARING_GROUPNAME); if (folders != null && folders.size() > 0) { OShare folder = folders.get(0); SharePermsFolder spf = core.getShareFolderPermissions(folder.getShareId().toString()); boolean shareIdentity = spf.implies("READ"); boolean forceMailcard = spf.implies("UPDATE"); if (shareIdentity) { id = new Identity(Identity.TYPE_AUTO, autoid--, null, udata.getDisplayName(), udata.getEmail().getAddress(), null, false, forceMailcard); id.setOriginPid(opid); idents.add(id); } } } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } return idents; } public List<ExternalAccount> listExternalAccounts() throws WTException { List<ExternalAccount> externalAccountList = new ArrayList<>(); Connection connection = null; ExternalAccountDAO dao = ExternalAccountDAO.getInstance(); try { connection = WT.getConnection(SERVICE_ID); UserProfileId userProfileId = getTargetProfileId(); List<OExternalAccount> externalAccounts = dao.selectByDomainUser(connection, userProfileId.getDomainId(), userProfileId.getUserId()); for (OExternalAccount externalAccount : externalAccounts) { ExternalAccount account = new ExternalAccount(); account.setExternalAccountId(externalAccount.getExternalAccountId()); account.setDisplayName(externalAccount.getDisplayName()); account.setAccountDescription(externalAccount.getDescription()); account.setEmail(externalAccount.getEmail()); account.setProtocol(externalAccount.getProtocol()); account.setHost(externalAccount.getHost()); account.setPort(externalAccount.getPort()); account.setReadOnly(externalAccount.getReadOnly()); account.setProviderId(externalAccount.getProviderId()); account.setUserName(externalAccount.getUsername()); account.setPassword(externalAccount.getPassword()); account.setFolderPrefix(externalAccount.getFolderPrefix()); account.setFolderSent(externalAccount.getFolderSent()); account.setFolderDrafts(externalAccount.getFolderDrafts()); account.setFolderTrash(externalAccount.getFolderTrash()); account.setFolderSpam(externalAccount.getFolderSpam()); account.setFolderArchive(externalAccount.getFolderArchive()); externalAccountList.add(account); } //externalAccountList = externalAccounts.stream().map(mapToExternalAccount()).collect(Collectors.toList()); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(connection); } return externalAccountList; } public ExternalAccount getExternalAccount(int externalAccountId) throws WTException { ExternalAccount externalAccount = null; Connection connection = null; ExternalAccountDAO dao = ExternalAccountDAO.getInstance(); try { connection = WT.getConnection(SERVICE_ID); externalAccount = mapToExternalAccount().apply(dao.selectById(connection, externalAccountId)); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(connection); } return externalAccount; } public void addExternalAccount(ExternalAccount account) throws WTException { Connection connection = null; ExternalAccountDAO dao = ExternalAccountDAO.getInstance(); try { OExternalAccount externalAccount = mapToOExternalAccount().apply(account); connection = WT.getConnection(SERVICE_ID); externalAccount.setExternalAccountId(dao.getSequence(connection).intValue()); UserProfileId userProfileId = getTargetProfileId(); externalAccount.setDomainId(userProfileId.getDomainId()); externalAccount.setUserId(userProfileId.getUserId()); dao.insert(connection, externalAccount); } catch (SQLException | DAOException ex) { StackTraceElement[] els = ex.getStackTrace(); for (StackTraceElement st : els) System.out.println(st.toString()); System.out.println(ex.getCause()); System.out.println(ex.getMessage()); throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(connection); } } public void removeExternalAccount(int externalAccountId) throws WTException { Connection connection = null; ExternalAccountDAO dao = ExternalAccountDAO.getInstance(); try { connection = WT.getConnection(SERVICE_ID); dao.deleteById(connection, externalAccountId); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(connection); } } public void updateExternalAccount(ExternalAccount account) throws WTException { Connection connection = null; ExternalAccountDAO dao = ExternalAccountDAO.getInstance(); try { OExternalAccount externalAccount = mapToOExternalAccount().apply(account); connection = WT.getConnection(SERVICE_ID); dao.update(connection, externalAccount); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(connection); } } private Function<OExternalAccount, ExternalAccount> mapToExternalAccount() { return externalAccount -> { ExternalAccount account = new ExternalAccount(); account.setExternalAccountId(externalAccount.getExternalAccountId()); account.setDisplayName(externalAccount.getDisplayName()); account.setAccountDescription(externalAccount.getDescription()); account.setEmail(externalAccount.getEmail()); account.setProtocol(externalAccount.getProtocol()); account.setHost(externalAccount.getHost()); account.setPort(externalAccount.getPort()); account.setReadOnly(externalAccount.getReadOnly()); account.setProviderId(externalAccount.getProviderId()); account.setUserName(externalAccount.getUsername()); account.setPassword(externalAccount.getPassword()); account.setFolderPrefix(externalAccount.getFolderPrefix()); account.setFolderSent(externalAccount.getFolderSent()); account.setFolderDrafts(externalAccount.getFolderDrafts()); account.setFolderTrash(externalAccount.getFolderTrash()); account.setFolderSpam(externalAccount.getFolderSpam()); account.setFolderArchive(externalAccount.getFolderArchive()); return account; }; } private Function<ExternalAccount, OExternalAccount> mapToOExternalAccount() { return externalAccount -> { OExternalAccount account = new OExternalAccount(); account.setExternalAccountId(externalAccount.getExternalAccountId()); account.setDisplayName(externalAccount.getDisplayName()); account.setDescription(externalAccount.getAccountDescription()); account.setEmail(externalAccount.getEmail()); account.setProtocol(externalAccount.getProtocol()); account.setHost(externalAccount.getHost()); account.setPort(externalAccount.getPort()); account.setReadOnly(externalAccount.isReadOnly()); account.setProviderId(externalAccount.getProviderId()); account.setUsername(externalAccount.getUserName()); account.setPassword(externalAccount.getPassword()); account.setFolderPrefix(externalAccount.getFolderPrefix()); account.setFolderSent(externalAccount.getFolderSent()); account.setFolderDrafts(externalAccount.getFolderDrafts()); account.setFolderTrash(externalAccount.getFolderTrash()); account.setFolderSpam(externalAccount.getFolderSpam()); account.setFolderArchive(externalAccount.getFolderArchive()); return account; }; } public Mailcard getMailcard() { UserProfileId pid = getTargetProfileId(); Data udata = WT.getUserData(pid); String domainId = pid.getDomainId(); String emailAddress = udata.getEmail().getAddress(); Mailcard mc = readEmailMailcard(domainId, emailAddress); if (mc != null) return mc; mc = readUserMailcard(domainId, pid.getUserId()); if (mc != null) return mc; mc = readEmailDomainMailcard(domainId, emailAddress); if (mc != null) return mc; return readDefaultMailcard(domainId); } public Mailcard getMailcard(UserProfileId pid) { Data udata = WT.getUserData(pid); String domainId = pid.getDomainId(); String emailAddress = udata.getEmail().getAddress(); Mailcard mc = readEmailMailcard(domainId, emailAddress); if (mc != null) return mc; mc = readUserMailcard(domainId, pid.getUserId()); if (mc != null) return mc; mc = readEmailDomainMailcard(domainId, emailAddress); if (mc != null) return mc; return readDefaultMailcard(domainId); } public Mailcard getMailcard(Identity identity) { UserProfileId pid = getTargetProfileId(); Mailcard mc = null; if (identity.getIdentityUid() != null) mc = readIdentityMailcard(pid.getDomainId(), identity); if (mc != null) return mc; mc = readEmailMailcard(pid.getDomainId(), identity.getEmail()); if (mc != null) return mc; UserProfileId fpid = identity.getOriginPid(); if (fpid != null) mc = readUserMailcard(fpid.getDomainId(), fpid.getUserId()); if (mc != null) return mc; mc = readEmailDomainMailcard(pid.getDomainId(), identity.getEmail()); if (mc != null) return mc; return readDefaultMailcard(pid.getDomainId()); } // public Mailcard getMailcard() { // return readDefaultMailcard(); // } public Mailcard getMailcard(String domainId, String emailAddress) { Mailcard mc = readEmailMailcard(domainId, emailAddress); if (mc != null) { return mc; } mc = readEmailDomainMailcard(domainId, emailAddress); if (mc != null) { return mc; } return readDefaultMailcard(domainId); } public Mailcard getEmailDomainMailcard(String domainId, String emailAddress) { Mailcard mc = readEmailDomainMailcard(domainId, emailAddress); if (mc != null) { return mc; } return getMailcard(); } private Mailcard readEmailMailcard(String domainId, String email) { String mailcard = readMailcard(domainId, "mailcard_" + email); if (mailcard != null) { return new Mailcard(Mailcard.TYPE_EMAIL, mailcard); } return null; } private Mailcard readEmailDomainMailcard(String domainId, String email) { int index = email.indexOf("@"); if (index < 0) { return null; } String mailcard = readMailcard(domainId, "mailcard_" + email.substring(index + 1)); if (mailcard != null) { return new Mailcard(Mailcard.TYPE_EMAIL_DOMAIN, mailcard); } return null; } private Mailcard readUserMailcard(String domainId, String user) { String mailcard = readMailcard(domainId, "mailcard_" + user); if (mailcard != null) { return new Mailcard(Mailcard.TYPE_USER, mailcard); } return null; } private Mailcard readDefaultMailcard(String domainId) { String mailcard = readMailcard(domainId, "mailcard"); if (mailcard != null) { return new Mailcard(Mailcard.TYPE_DEFAULT, mailcard); } return new Mailcard(); } private Mailcard readIdentityMailcard(String domainId, Identity identity) { String mailcard = readMailcard(domainId, "mailcard_" + identity.getEmail() + "_" + identity.getIdentityUid()); if (mailcard != null) { return new Mailcard(Mailcard.TYPE_EMAIL, mailcard); } return null; } public void setIdentityMailcard(Identity ident, String html) { String domainId = getTargetProfileId().getDomainId(); if (ident.getIdentityUid() == null) setEmailMailcard(ident.getEmail(), html); else writeMailcard(domainId, "mailcard_" + ident.getEmail() + "_" + ident.getIdentityUid(), html); } public void setUserMailcard(String html) { ensureProfileDomain(true); if (RunContext.isWebTopAdmin() || RunContext.isPermitted(true, getTargetProfileId(), SERVICE_ID, "MAILCARD_SETTINGS", "CHANGE")) { writeMailcard(getTargetProfileId().getDomainId(), "mailcard_" + getTargetProfileId().getUserId(), html); } else { throw new AuthException("You have insufficient rights to perform the operation [{}]", "MAILCARD_SETTINGS:CHANGE"); } } public void setEmailMailcard(String email, String html) { ensureProfileDomain(true); if (RunContext.isWebTopAdmin() || RunContext.isPermitted(true, getTargetProfileId(), SERVICE_ID, "MAILCARD_SETTINGS", "CHANGE")) { writeMailcard(getTargetProfileId().getDomainId(), "mailcard_" + email, html); } else { throw new AuthException("You have insufficient rights to perform the operation [{}]", "MAILCARD_SETTINGS:CHANGE"); } } public void setEmailDomainMailcard(String email, String html) { ensureProfileDomain(true); if (RunContext.isWebTopAdmin() || RunContext.isPermitted(true, getTargetProfileId(), SERVICE_ID, "DOMAIN_MAILCARD_SETTINGS", "CHANGE")) { if (!StringUtils.contains(email, "@")) return; writeMailcard(getTargetProfileId().getDomainId(), "mailcard_" + StringUtils.substringAfterLast(email, "@"), html); } else { throw new AuthException("You have insufficient rights to perform the operation [{}]", "DOMAIN_MAILCARD_SETTINGS:CHANGE"); } } private void writeMailcard(String domainId, String filename, String html) { String pathname = MessageFormat.format("{0}/{1}.html", getModelPath(domainId), filename); try { File file = new File(pathname); if (html != null) { FileUtils.write(file, html, "ISO-8859-15"); } else { FileUtils.forceDelete(file); } } catch (FileNotFoundException ex) { logger.trace("Cleaning not necessary. Mailcard file not found. [{}]", pathname, ex); } catch (IOException ex) { logger.error("Unable to write/delete mailcard file. [{}]", pathname, ex); } } private String readMailcard(String domainId, String filename) { String pathname = MessageFormat.format("{0}/{1}.html", getModelPath(domainId), filename); try { File file = new File(pathname); return FileUtils.readFileToString(file, "ISO-8859-15"); } catch (FileNotFoundException ex) { logger.trace("Mailcard file not found. [{}]", pathname); return null; } catch (IOException ex) { logger.error("Unable to read mailcard file. [{}]", pathname, ex); } return null; } public String getModelPath(String domainId) { String path = PathUtils.concatPathParts(WT.getServiceHomePath(domainId, SERVICE_ID), "models"); return path; } public List<Tag> getTags() throws WTException { TagDAO tagdao = TagDAO.getInstance(); List<Tag> tags = new ArrayList<>(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); List<OTag> items = tagdao.selectByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); for (OTag item : items) { tags.add(createTag(item)); } return tags; } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void addTag(Tag tag) throws WTException { TagDAO tagdao = TagDAO.getInstance(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); tagdao.insert(con, createTag(getTargetProfileId().getDomainId(), getTargetProfileId().getUserId(), tag)); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void removeTag(String tagId) throws WTException { TagDAO tagdao = TagDAO.getInstance(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); tagdao.deleteById(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId(), tagId); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void updateTag(Tag tag, String newTagId) throws WTException { TagDAO tagdao = TagDAO.getInstance(); Connection con = null; String oldTagId = ""; try { con = WT.getConnection(SERVICE_ID); oldTagId = tag.getTagId(); tag.setTagId(newTagId); tagdao.update(con, oldTagId, createTag(getTargetProfileId().getDomainId(), getTargetProfileId().getUserId(), tag)); } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void updateFoldersTag(String oldTagId, String newTagId, Collection<FolderCache> folders, SearchTerm searchTerm, boolean hasAttachment) { for (FolderCache fc : folders) { Message msgs[] = null; try { msgs = fc.getMessages(FolderCache.SORT_BY_DATE, false, true, -1, true, false, searchTerm, hasAttachment); long[] uid = new long[msgs.length]; for (int i = 0; i < msgs.length; i++) { uid[i] = fc.getUID(msgs[i]); } fc.untagMessages(uid, oldTagId); fc.tagMessages(uid, newTagId); } catch (MessagingException ex) { logger.error("Error updating folder tags on " + fc.getFolderName(), ex); } catch (IOException ex) { logger.error("Error updating folder tags on " + fc.getFolderName(), ex); } } } public String sanitazeTagId(String tagId) { tagId = tagId.replace(" ", "_"); tagId = tagId.replace("%", "_"); tagId = tagId.replace("*", "_"); tagId = tagId.replace("\\", "_"); tagId = tagId.replace("]", "_"); tagId = tagId.replace("[", "_"); for (char c = 1; c < 32; ++c) tagId = tagId.replace(String.valueOf(c), "_"); return tagId; } private static Tag builtinTags[] = { new Tag("$label1", "$Label1", "#ff003a"), new Tag("$label2", "$Label2", "#ff9900"), new Tag("$label3", "$Label3", "#009900"), new Tag("$label4", "$Label4", "#3333ff"), new Tag("$label5", "$Label5", "#993399") }; protected void addBuiltinTags() throws WTException { TagDAO tagdao = TagDAO.getInstance(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); for (Tag tag : builtinTags) { try { tagdao.insert(con, new OTag(getTargetProfileId().getDomainId(), getTargetProfileId().getUserId(), tag.getTagId(), lookupResource(getLocale(), MailLocaleKey.TAGS_LABEL(tag.getTagId())), tag.getColor())); } catch (DataAccessException exc) { } } } catch (SQLException ex) { throw new WTException(ex); } finally { DbUtils.closeQuietly(con); } } private Tag createTag(OTag otag) { if (otag == null) return null; Tag tag = new Tag(otag.getTagId(), otag.getDescription(), otag.getColor()); return tag; } private OTag createTag(String domainId, String userId, Tag tag) { if (tag == null) return null; OTag otag = new OTag(); otag.setDomainId(domainId); otag.setUserId(userId); otag.setTagId(tag.getTagId()); otag.setDescription(tag.getDescription()); otag.setColor(tag.getColor()); return otag; } public boolean isAutoResponderActive() throws WTException { AutoResponderDAO autdao = AutoResponderDAO.getInstance(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); OAutoResponder oaut = autdao.selectByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); return (oaut != null) ? oaut.getEnabled() : false; } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public AutoResponder getAutoResponder() throws WTException { AutoResponderDAO autdao = AutoResponderDAO.getInstance(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); OAutoResponder oaut = autdao.selectByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); if (oaut == null) { return new AutoResponder(); } else { return createAutoResponder(oaut); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void updateAutoResponder(AutoResponder autoResponder) throws WTException { AutoResponderDAO autdao = AutoResponderDAO.getInstance(); Connection con = null; //TODO: valutare permessi... admin? try { con = WT.getConnection(SERVICE_ID); OAutoResponder oaut = createOAutoResponder(autoResponder); oaut.setDomainId(getTargetProfileId().getDomainId()); oaut.setUserId(getTargetProfileId().getUserId()); boolean exist = autdao.existByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); if (exist) { autdao.update(con, oaut); } else { autdao.insert(con, oaut); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public List<MailFilter> getMailFilters(MailFiltersType type) throws WTException { return getMailFilters(type, false); } public List<MailFilter> getMailFilters(MailFiltersType type, boolean enabledOnly) throws WTException { InFilterDAO indao = InFilterDAO.getInstance(); List<MailFilter> filters = new ArrayList<>(); Connection con = null; try { con = WT.getConnection(SERVICE_ID); if (type.equals(MailFiltersType.INCOMING)) { List<OInFilter> items = indao.selectByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); if (enabledOnly) { items = indao.selectEnabledByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); } else { items = indao.selectByProfile(con, getTargetProfileId().getDomainId(), getTargetProfileId().getUserId()); } for (OInFilter item : items) { filters.add(createMailFilter(item)); } return filters; } else { throw new WTException("Type not supported yet [{0}]", type.toString()); } } catch (SQLException | DAOException ex) { throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public void updateMailFilters(MailFiltersType type, List<MailFilter> filters) throws WTException { InFilterDAO indao = InFilterDAO.getInstance(); Connection con = null; //TODO: valutare permessi... admin? try { con = WT.getConnection(SERVICE_ID, false); if (type.equals(MailFiltersType.INCOMING)) { List<MailFilter> origFilters = getMailFilters(type); CollectionChangeSet<MailFilter> changeSet = LangUtils.getCollectionChanges(origFilters, filters); OInFilter ofil = null; for (MailFilter filter : changeSet.inserted) { ofil = createOInFilter(filter); ofil.setInFilterId(indao.getSequence(con).intValue()); ofil.setDomainId(getTargetProfileId().getDomainId()); ofil.setUserId(getTargetProfileId().getUserId()); indao.insert(con, ofil); } for (MailFilter filter : changeSet.updated) { ofil = createOInFilter(filter); indao.update(con, ofil); } for (MailFilter filter : changeSet.deleted) { indao.delete(con, filter.getFilterId()); } DbUtils.commitQuietly(con); } else { throw new WTException("Type not supported yet [{0}]", type.toString()); } } catch (SQLException | DAOException ex) { DbUtils.rollbackQuietly(con); throw new WTException(ex, "DB error"); } finally { DbUtils.closeQuietly(con); } } public List<SieveScript> listSieveScripts() throws WTException { ManageSieveClient client = null; ensureUserDomain(); try { client = createSieveClient(); return SieveHelper.listScripts(client); } finally { SieveHelper.logoutSieveClientQuietly(client); } } public String getActiveSieveScriptName() throws WTException { ManageSieveClient client = null; ensureUserDomain(); try { client = createSieveClient(); return SieveHelper.getActiveScript(client); } finally { SieveHelper.logoutSieveClientQuietly(client); } } public void activateSieveScript(String name) throws WTException { ManageSieveClient client = null; ensureUser(); try { client = createSieveClient(); SieveHelper.activateScript(client, name); } finally { SieveHelper.logoutSieveClientQuietly(client); } } public void applySieveScript(boolean activate) throws WTException { UserProfile.Data ud = WT.getUserData(getTargetProfileId()); SieveScriptBuilder ssb = new SieveScriptBuilder(); MailServiceSettings mss = new MailServiceSettings(SERVICE_ID, getTargetProfileId().getDomainId()); MailUserSettings mus = new MailUserSettings(getTargetProfileId(), mss); if (!mss.isSieveSpamFilterDisabled()) ssb.setSpamFilter(mus.getFolderSpam()); ensureUser(); logger.debug("Working on autoresponder..."); AutoResponder autoResp = getAutoResponder(); if (autoResp.getEnabled()) { ssb.setVacation(autoResp.toSieveVacation(ud.getPersonalEmail(), ud.getTimeZone())); } logger.debug("Working on incoming filters..."); List<MailFilter> filters = getMailFilters(MailFiltersType.INCOMING); // Arrange filters in the specified order and fill the builder Collections.sort(filters, new Comparator<MailFilter>() { @Override public int compare(MailFilter o1, MailFilter o2) { return Short.compare(o1.getOrder(), o2.getOrder()); } }); for (MailFilter filter : filters) { if (filter.getEnabled()) { ssb.addFilter(filter.getName(), filter.getSieveMatch(), filter.getSieveRules(), filter.getSieveActions()); } } String script = buildSieveScriptHeader() + ssb.build(); ManageSieveClient client = null; try { if (sieveConfig == null) throw new WTException( "SieveConfiguration not defined. Please call setSieveConfiguration(...) before call this method!"); client = createSieveClient(); SieveHelper.putScript(client, SIEVE_WEBTOP_SCRIPT, script); if (activate) { SieveHelper.activateScript(client, SIEVE_WEBTOP_SCRIPT); } } finally { SieveHelper.logoutSieveClientQuietly(client); } } private ManageSieveClient createSieveClient() throws WTException { if (sieveConfig == null) throw new WTException( "SieveConfiguration not defined. Please call setSieveConfiguration(...) before using Sieve!"); return SieveHelper.createSieveClient(sieveConfig.getHost(), sieveConfig.getPort(), sieveConfig.getUsername(), sieveConfig.getPassword()); } private String buildSieveScriptHeader() { DateTimeFormatter fmt = DateTimeUtils.createYmdHmsFormatter(); StringBuilder sb = new StringBuilder(); sb.append("# Generated by WebTop [http://www.sonicle.com]"); sb.append("\n"); sb.append("# ").append(SERVICE_ID).append("@").append(WT.getManifest(SERVICE_ID).getVersion().toString()); sb.append("\n"); sb.append("# ").append(fmt.print(DateTimeUtils.now())); sb.append("\n"); sb.append("\n"); return sb.toString(); } private AutoResponder createAutoResponder(OAutoResponder oaut) { if (oaut == null) return null; AutoResponder aut = new AutoResponder(); aut.setEnabled(oaut.getEnabled()); aut.setSubject(oaut.getSubject()); aut.setMessage(oaut.getMessage()); aut.setAddresses(oaut.getAddresses()); aut.setDaysInterval(oaut.getDaysInterval()); aut.setActivationStartDate(oaut.getStartDate()); aut.setActivationEndDate(oaut.getEndDate()); aut.setSkipMailingLists(oaut.getSkipMailingLists()); return aut; } private OAutoResponder createOAutoResponder(AutoResponder aut) { if (aut == null) return null; OAutoResponder oaut = new OAutoResponder(); oaut.setEnabled(aut.getEnabled()); oaut.setSubject(aut.getSubject()); oaut.setMessage(aut.getMessage()); oaut.setAddresses(aut.getAddresses()); oaut.setDaysInterval(aut.getDaysInterval()); oaut.setStartDate(aut.getActivationStartDate()); oaut.setEndDate(aut.getActivationEndDate()); oaut.setSkipMailingLists(aut.getSkipMailingLists()); return oaut; } private OInFilter createOInFilter(MailFilter fil) { if (fil == null) return null; OInFilter ofil = new OInFilter(); ofil.setInFilterId(fil.getFilterId()); ofil.setEnabled(fil.getEnabled()); ofil.setOrder(fil.getOrder()); ofil.setName(fil.getName()); ofil.setSieveMatch(EnumUtils.toSerializedName(fil.getSieveMatch())); ofil.setSieveRules(LangUtils.serialize(fil.getSieveRules(), SieveRuleList.class)); ofil.setSieveActions(LangUtils.serialize(fil.getSieveActions(), SieveActionList.class)); return ofil; } private MailFilter createMailFilter(OInFilter ofil) { if (ofil == null) return null; MailFilter fil = new MailFilter(); fil.setFilterId(ofil.getInFilterId()); fil.setEnabled(ofil.getEnabled()); fil.setOrder(ofil.getOrder()); fil.setName(ofil.getName()); fil.setSieveMatch(EnumUtils.forSerializedName(ofil.getSieveMatch(), SieveMatch.class)); SieveRuleList rules = LangUtils.deserialize(ofil.getSieveRules(), null, SieveRuleList.class); if (rules != null) fil.getSieveRules().addAll(rules); SieveActionList acts = LangUtils.deserialize(ofil.getSieveActions(), null, SieveActionList.class); if (acts != null) fil.getSieveActions().addAll(acts); return fil; } private static class SieveConfig { private String host; private int port; private String username; private char[] password; public SieveConfig(String host, int port, String username, String password) { this.host = host; this.port = port; this.username = username; this.password = password.toCharArray(); } public String getHost() { return host; } public int getPort() { return port; } public String getUsername() { return username; } public String getPassword() { return new String(password); } } }