package org.esupportail.helpdesk.services.feed.imap; import java.util.Properties; import javax.mail.Flags; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.Session; import javax.mail.Store; import javax.mail.URLName; import org.esupportail.commons.utils.Assert; import org.esupportail.helpdesk.domain.beans.Ticket; import org.esupportail.helpdesk.domain.beans.User; import org.esupportail.helpdesk.exceptions.TicketNotFoundException; import org.esupportail.helpdesk.services.feed.ErrorHolder; import org.esupportail.helpdesk.services.feed.imap.messageId.MessageIdException; import org.esupportail.helpdesk.services.feed.imap.messageId.MessageIdHandler; /** * A class to generate tickets from an email account. */ public final class ActionAccountReaderImpl extends AbstractImapAccountReader { /** * The serialization id. */ private static final long serialVersionUID = 3952279216168621460L; /** * The message reader. */ private ActionMessageReader messageReader; /** * The message id handler. */ private MessageIdHandler messageIdHandler; /** * Constructor. */ public ActionAccountReaderImpl() { super(); } /** * @see org.esupportail.helpdesk.services.feed.imap.AbstractImapAccountReader#afterPropertiesSet() */ @Override public void afterPropertiesSet() { super.afterPropertiesSet(); if (isEnabled()) { Assert.notNull(messageReader, "property messageReader of class " + this.getClass().getName() + " can not be null"); Assert.notNull(messageIdHandler, "property messageIdHandler of class " + this.getClass().getName() + " can not be null"); } } /** * @see org.esupportail.helpdesk.services.feed.AccountReader#read( * org.esupportail.helpdesk.services.feed.ErrorHolder) */ @Override public boolean read(final ErrorHolder errorHolder) { Ticket ticket = null; Store store = null; User sender = null; if (!errorHolder.hasErrors()) { try { errorHolder.addInfo("Server: " + getServer()); errorHolder.addInfo("Folder: " + getFolder()); errorHolder.addInfo("Account: " + getAccount()); errorHolder.addInfo("Password: " + "xxxxxxxxx"); Integer timeoutVal = new Integer(getTimeout()); Properties props = System.getProperties(); props.put("mail.imap.class", "com.sun.mail.imap.IMAPStore"); props.put("mail.imap.connectiontimeout", timeoutVal); props.put("mail.imap.timeout", timeoutVal); Session session = Session.getInstance(props, null); URLName urln = new URLName( "imap://" + getAccount() + ":" + getPassword() + "@" + getServer()); store = session.getStore(urln); } catch (NoSuchProviderException e) { errorHolder.addError( "invalid IMAP account [imap://" + getAccount() + ":xxxxxxxx@" + getServer() + "]: " + e.getMessage()); } } if (!errorHolder.hasErrors()) { try { errorHolder.addInfo("connecting to the server..."); store.connect(); } catch (MessagingException e) { errorHolder.addError( "could not connect to [imap://" + getAccount() + ":xxxxxxxx@" + getServer() + "]: " + e.getMessage()); } } Folder folder = null; if (!errorHolder.hasErrors()) { try { errorHolder.addInfo("opening folder [" + getFolder() + "]..."); folder = store.getFolder(getFolder()); if (!folder.exists()) { String msg = "folder does not exist. Available folders are: "; Folder defaultFolder = store.getDefaultFolder(); String separator = ""; for (Folder folder2 : defaultFolder.list()) { msg += separator + folder2.getFullName(); separator = ", "; } errorHolder.addError(msg + "."); } } catch (MessagingException e) { errorHolder.addError("could not find the folder: " + e.getMessage()); } } if (!errorHolder.hasErrors()) { try { folder.open(Folder.READ_WRITE); } catch (MessagingException e) { errorHolder.addError("could not open the folder: " + e.getMessage()); } } if (!errorHolder.hasErrors()) { try { errorHolder.addInfo("expunging the folder..."); folder.expunge(); } catch (MessagingException e) { errorHolder.addError("could not expunge the folder: " + e.getMessage()); } } int messageCount = 0; if (!errorHolder.hasErrors()) { try { messageCount = folder.getMessageCount(); if (messageCount == 0) { errorHolder.addInfo("no message found."); } else { errorHolder.addInfo(messageCount + " message(s) found."); } } catch (MessagingException e) { errorHolder.addError("could not get the number of messages: " + e.getMessage()); } } if (!errorHolder.hasErrors()) { for (int i = 1; i <= messageCount; i++) { errorHolder.addInfo("getting message #" + i + "..."); Message message; try { message = folder.getMessage(i); ticket = getTicketFromHeaders(message, errorHolder); } catch (MessagingException e) { errorHolder.addError( "could not get message #" + i + ": " + e.getMessage()); break; } try { if (message.isSet(Flags.Flag.DELETED)) { errorHolder.addInfo("message is marked as deleted, skiping."); continue; } } catch (MessagingException e) { errorHolder.addError( "could not get flag for message #" + i + ": " + e.getMessage()); break; } ErrorHolder readErrorHolder = new ErrorHolder(); if (ticket != null) { sender = messageReader.readMessage(message, ticket, readErrorHolder); } try { message.setFlag(Flags.Flag.DELETED, true); } catch (MessagingException e) { errorHolder.addInfo("could not mark the message as deleted: " + e.getMessage()); } errorHolder.add(readErrorHolder); break; } } if (folder != null && folder.isOpen()) { try { errorHolder.addInfo("closing folder..."); folder.close(true/* expunge on exit */); } catch (MessagingException e) { errorHolder.addError("could not close the folder: " + e.getMessage()); } } if (store != null && store.isConnected()) { try { errorHolder.addInfo("closing connection..."); store.close(); } catch (MessagingException e) { errorHolder.addError("could not close the connection: " + e.getMessage()); } } if (errorHolder.hasErrors()) { errorHolder.addInfo( errorHolder.getErrorNumber() + " error(s) found for account [imap://" + getAccount() + ":xxxxxxxx@" + getServer() + "]"); } else { errorHolder.addInfo( "no error found for account [imap://" + getAccount() + ":xxxxxxxx@" + getServer() + "]"); } if (ticket == null) { return false; } getDomainService().ticketMonitoringSendAlerts(sender, ticket, null, false); return true; } /** * @param message Email message * @param header Message header to examine * @return Found ticket * @throws MessagingException Error processing message * @throws TicketNotFoundException Error getting ticket * @throws MessagingException */ private Ticket getTicketFromHeader( final Message message, final String header) throws TicketNotFoundException, MessagingException { String[] headers; headers = message.getHeader(header); if (headers != null) { for (String headerItem : headers) { Long ticketId = null; try { ticketId = messageIdHandler.getTicketIdFromMessageId(headerItem); return getDomainService().getTicket(ticketId); } catch (MessageIdException e) { // error } } } return null; } /** * Finds ticket id in email headers and returns the found ticket. * @param message Email message * @param errorHolder Error holder * @return Found ticket * @throws MessagingException Exception */ private Ticket getTicketFromHeaders( final Message message, final ErrorHolder errorHolder) throws MessagingException { Ticket ticket; try { ticket = getTicketFromHeader(message, "In-Reply-To"); if (ticket != null) { errorHolder.addInfo("Found ticket #" + ticket.getId() + " in In-Reply-To"); return ticket; } } catch (TicketNotFoundException e) { //Ticket not found. Probably missformed header. We try to find it in References. } try { ticket = getTicketFromHeader(message, "References"); if (ticket != null) { errorHolder.addInfo("Found ticket #" + ticket.getId() + " in References"); return ticket; } } catch (TicketNotFoundException e) { //Ticket not found. Probably missformed header.. } //TODO LS: Extract ticket number from subject PA: what about SPAM? errorHolder.addError("No ticket number found in headers... => ignore message"); return null; } /** * @return the messageReader */ protected ActionMessageReader getMessageReader() { return messageReader; } /** * @param messageReader the messageReader to set */ public void setMessageReader(final ActionMessageReader messageReader) { this.messageReader = messageReader; } /** * @return the messageIdHandler */ protected MessageIdHandler getMessageIdHandler() { return messageIdHandler; } /** * @param messageIdHandler the messageIdHandler to set */ public void setMessageIdHandler(final MessageIdHandler messageIdHandler) { this.messageIdHandler = messageIdHandler; } }