diff --git a/gxmail/src/main/java/com/genexus/internet/POP3SessionJavaMail.java b/gxmail/src/main/java/com/genexus/internet/POP3SessionJavaMail.java index 791f9788d..c496647bf 100644 --- a/gxmail/src/main/java/com/genexus/internet/POP3SessionJavaMail.java +++ b/gxmail/src/main/java/com/genexus/internet/POP3SessionJavaMail.java @@ -1,11 +1,11 @@ package com.genexus.internet; import java.io.*; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; +import java.nio.file.Paths; +import java.util.regex.Pattern; import com.genexus.diagnostics.core.ILogger; import com.genexus.diagnostics.core.LogManager; @@ -27,8 +27,7 @@ import com.sun.mail.pop3.POP3Folder; import com.sun.mail.pop3.POP3Store; -public class POP3SessionJavaMail implements GXInternetConstants,IPOP3Session -{ +public class POP3SessionJavaMail implements GXInternetConstants, IPOP3Session { public static final ILogger logger = LogManager.getLogger(POP3SessionJavaMail.class); private String user; @@ -45,33 +44,30 @@ public class POP3SessionJavaMail implements GXInternetConstants,IPOP3Session private int numOfMessages; private int lastReadMessage; private StringCollection attachs; - + private Session session; private POP3Store emailStore; private Boolean downloadAttachments = false; - + Message[] messages; POP3Folder emailFolder; - public POP3SessionJavaMail() - { - } + public POP3SessionJavaMail() {} - public void login(GXPOP3Session sessionInfo) - { + public void login(GXPOP3Session sessionInfo) { this.pop3Host = sessionInfo.getHost(); this.pop3Port = sessionInfo.getPort(); - this.timeout = sessionInfo.getTimeout(); + this.timeout = sessionInfo.getTimeout(); this.user = sessionInfo.getUserName(); this.password = sessionInfo.getPassword(); - this.deleteOnRead = false; + this.deleteOnRead = false; this.readSinceLast = sessionInfo.getNewMessages() != 0; this.secureConnection = sessionInfo.getSecure() != 0; - + timeout = timeout * 1000; Properties props = new Properties(); props.setProperty("mail.pop3.host", pop3Host); - props.setProperty("mail.pop3.port", String.valueOf(pop3Port)); + props.setProperty("mail.pop3.port", String.valueOf(pop3Port)); props.setProperty("mail.pop3.connectiontimeout", String.valueOf(timeout)); props.setProperty("mail.pop3.timeout", String.valueOf(timeout)); @@ -84,339 +80,273 @@ public void login(GXPOP3Session sessionInfo) } props.setProperty("mail.pop3.ssl.enable", String.valueOf(secureConnection)); - + session = Session.getInstance(props); - if (logger.isDebugEnabled()) - { + if (logger.isDebugEnabled()) { session.setDebug(true); - } - try - { + } + try { emailStore = (POP3Store) session.getStore("pop3"); emailStore.connect(user, password); - + emailFolder = (POP3Folder) emailStore.getFolder("INBOX"); emailFolder.open(Folder.READ_WRITE); lastReadMessage = 0; - - if (readSinceLast) - { + + if (readSinceLast) { numOfMessages = emailFolder.getNewMessageCount(); - } - else - { + } else { numOfMessages = emailFolder.getMessageCount(); } messages = emailFolder.getMessages(); - } - catch(NoSuchProviderException e) - { - log (e.getMessage()); + } catch (NoSuchProviderException e) { + log(e.getMessage()); + sessionInfo.exceptionHandler(new GXMailException("Can't connect to mail server", MAIL_CantLogin)); + } catch (MessagingException me) { + log(me.getMessage()); sessionInfo.exceptionHandler(new GXMailException("Can't connect to mail server", MAIL_CantLogin)); } - catch(MessagingException me) - { - log (me.getMessage()); - sessionInfo.exceptionHandler(new GXMailException("Can't connect to mail server", MAIL_CantLogin)); - } } - public void logout(GXPOP3Session sessionInfo) - { - try - { + public void logout(GXPOP3Session sessionInfo) { + try { emailFolder.close(true); emailStore.close(); - } - catch (MessagingException e) - { - log (e.getMessage()); + } catch (MessagingException e) { + log(e.getMessage()); sessionInfo.exceptionHandler(new GXMailException(e.getMessage(), MAIL_ConnectionLost)); } } - public void delete(GXPOP3Session sessionInfo) - { - try - { - messages[lastReadMessage-1].setFlag(Flags.Flag.DELETED, true); - } - catch (MessagingException e) - { - log (e.getMessage()); + public void delete(GXPOP3Session sessionInfo) { + try { + messages[lastReadMessage - 1].setFlag(Flags.Flag.DELETED, true); + } catch (MessagingException e) { + log(e.getMessage()); sessionInfo.exceptionHandler(new GXMailException(e.getMessage(), MAIL_ServerRepliedErr)); } } - public void skip(GXPOP3Session sessionInfo) - { - try - { - if (lastReadMessage == numOfMessages) + public void skip(GXPOP3Session sessionInfo) { + try { + if (lastReadMessage == numOfMessages) throw new GXMailException("No messages to receive", MAIL_NoMessages); - + ++lastReadMessage; - } - catch (GXMailException e) - { + } catch (GXMailException e) { sessionInfo.exceptionHandler(e); - } + } } - - public void receive(GXPOP3Session sessionInfo, GXMailMessage gxmessage) - { - try - { + + public void receive(GXPOP3Session sessionInfo, GXMailMessage gxmessage) { + try { gxmessage.clear(); - setAttachmentsPath(sessionInfo.getAttachDir()); - - if (lastReadMessage +1 > numOfMessages) + setAttachmentsPath(sessionInfo.getAttachDir()); + + if (lastReadMessage + 1 > numOfMessages) throw new GXMailException("No messages to receive", MAIL_NoMessages); - + Message message = messages[lastReadMessage++]; - gxmessage.setFrom(getMailRecipient((InternetAddress)message.getFrom()[0])); - - - gxmessage.setTo(processRecipients(message, Message.RecipientType.TO)); + gxmessage.setFrom(getMailRecipient((InternetAddress) message.getFrom()[0])); + + gxmessage.setTo(processRecipients(message, Message.RecipientType.TO)); gxmessage.setCc(processRecipients(message, Message.RecipientType.CC)); gxmessage.setBcc(processRecipients(message, Message.RecipientType.BCC)); - + MailRecipientCollection mailRecipient = new MailRecipientCollection(); - for (int i = 0 ; i < message.getReplyTo().length; i++) - { - InternetAddress addr = ((InternetAddress)message.getReplyTo()[i]); - mailRecipient.addNew(addr.getPersonal(), addr.getAddress()); + for (int i = 0; i < message.getReplyTo().length; i++) { + InternetAddress addr = ((InternetAddress) message.getReplyTo()[i]); + mailRecipient.addNew(addr.getPersonal(), addr.getAddress()); } - + gxmessage.setReplyto(mailRecipient); - + gxmessage.setDateSent(message.getSentDate()); - gxmessage.setDateReceived(message.getReceivedDate() == null ? com.genexus.CommonUtil.now(): message.getReceivedDate()); - + gxmessage.setDateReceived(message.getReceivedDate() == null ? com.genexus.CommonUtil.now() : message.getReceivedDate()); + gxmessage.setSubject(message.getSubject()); Hashtable headers = new Hashtable(); - for (Enumeration en = message.getAllHeaders(); en.hasMoreElements(); ) - { + for (Enumeration en = message.getAllHeaders(); en.hasMoreElements();) { Header h = (Header) en.nextElement(); headers.put(h.getName(), h.getValue()); } gxmessage.setHeaders(headers); - + attachs = new StringCollection(); - Object content = message.getContent(); - if (content instanceof Multipart) - { - handleMultipart((Multipart)content, gxmessage); - } - else - { - handlePart(message, gxmessage); - } - } - catch (GXMailException e) - { + Object content = message.getContent(); + if (content instanceof Multipart) { + handleMultipart((Multipart) content, gxmessage); + } else { + handlePart(message, gxmessage); + } + } catch (GXMailException e) { sessionInfo.exceptionHandler(e); - } - catch (MessagingException e) - { - log (e.getMessage()); + } catch (MessagingException e) { + log(e.getMessage()); + sessionInfo.exceptionHandler(new GXMailException(e.getMessage(), MAIL_ServerRepliedErr)); + } catch (IOException e) { + log(e.getMessage()); sessionInfo.exceptionHandler(new GXMailException(e.getMessage(), MAIL_ServerRepliedErr)); - } - catch (IOException e) - { - log (e.getMessage()); - sessionInfo.exceptionHandler(new GXMailException(e.getMessage(), MAIL_ServerRepliedErr)); } } - - private MailRecipient getMailRecipient(InternetAddress inetAdd) - { - return new MailRecipient(inetAdd.getPersonal(), inetAdd.getAddress()); + + private MailRecipient getMailRecipient(InternetAddress inetAdd) { + return new MailRecipient(inetAdd.getPersonal(), inetAdd.getAddress()); } - - private MailRecipientCollection processRecipients(Message message, Message.RecipientType rType) throws MessagingException - { + + private MailRecipientCollection processRecipients(Message message, Message.RecipientType rType) throws MessagingException { MailRecipientCollection mailRecipient = new MailRecipientCollection(); try { - if (message.getRecipients(rType) != null) - { - for (int i = 0 ; i < message.getRecipients(rType).length; i++) - { - InternetAddress address = (InternetAddress)message.getRecipients(rType)[i]; + if (message.getRecipients(rType) != null) { + for (int i = 0; i < message.getRecipients(rType).length; i++) { + InternetAddress address = (InternetAddress) message.getRecipients(rType)[i]; mailRecipient.addNew(address.getPersonal(), address.getAddress()); } } return mailRecipient; } catch (AddressException e) { - /* - Some email clients like Gmail separate the list of addresses using commas while others like Outlook separate them using - semicolons. This is a hack to consider the case where the list of addresses is separated with semicolons which produces - an exception because the InternetAddress class used by jakarta mail to parse the addresses expects the list to be separated by commas - */ - String[] addresses = message.getHeader(rType.toString()); + /* + Some email clients like Gmail separate the list of addresses using commas while others like Outlook separate them using + semicolons. This is a hack to consider the case where the list of addresses is separated with semicolons which produces + an exception because the InternetAddress class used by jakarta mail to parse the addresses expects the list to be separated by commas + */ + String[] addresses = message.getHeader(rType.toString()); if (addresses != null && addresses.length > 0) { - for (String address : addresses) { + for (String address: addresses) { String[] splitAddresses = address.split(";"); - for (String splitAddress : splitAddresses){ + for (String splitAddress: splitAddresses) { InternetAddress ia = new InternetAddress(splitAddress); - mailRecipient.addNew(ia.getPersonal(),ia.getAddress()); + mailRecipient.addNew(ia.getPersonal(), ia.getAddress()); } } } return mailRecipient; } } - - private void handleMultipart(Multipart multipart, GXMailMessage gxmessage) throws MessagingException, IOException - { - for (int i=0, n=multipart.getCount(); i")) - { - cid = cids[0].substring(1, cids[0].length() - 1); - } - return cid; - } - - private void saveFile(String filename, InputStream input) throws IOException - { - try { - String encodedFilename = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString()); - encodedFilename = encodedFilename.replace("+", "_"); - File file = new File(attachmentsPath + encodedFilename); - try (FileOutputStream fos = new FileOutputStream(file); - BufferedOutputStream bos = new BufferedOutputStream(fos); - BufferedInputStream bis = new BufferedInputStream(input)) { - int aByte; - while ((aByte = bis.read()) != -1) { - bos.write(aByte); - } - bos.flush(); - } - } catch (UnsupportedEncodingException e) { - throw new IOException("Error encoding the filename", e); - } - } - - public String getNextUID() throws GXMailException - { - try - { - if (lastReadMessage == numOfMessages) + if (part.isMimeType("text/html")) { + gxmessage.setHtmltext(part.getContent().toString()); + } + if (part.isMimeType("multipart/*")) { + handleMultipart((Multipart) part.getContent(), gxmessage); + } + if (disposition == null && part.isMimeType("application/*")) { + disposition = "UNKNOWN"; + } + if (this.downloadAttachments && (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE) || disposition.equalsIgnoreCase("UNKNOWN")))) { + String fileName = ""; + if (part.getFileName() != null) + fileName = MimeUtility.decodeText(part.getFileName()); + else if (isXForwardedFor && ((MimeMessage) part.getContent()).getFileName() != null) + fileName = MimeUtility.decodeText(((MimeMessage) part.getContent()).getFileName()); + else if (!(part.getContent() instanceof MimeMessage) || ((MimeMessage) part.getContent()).getFileName() == null) + fileName = SpecificImplementation.GXutil.getTempFileName("tmp"); + + String cid = getAttachmentContentId(part); + if (disposition.equalsIgnoreCase(Part.INLINE) && !cid.isEmpty()) { + fileName = String.format("%s_%s", cid, fileName); + String newHTML = gxmessage.getHtmltext().replace(cid, fileName); + gxmessage.setHtmltext(newHTML); + } + + try (InputStream is = part.getContent() instanceof MimeMessage ? ((MimeMessage) part.getContent()).getInputStream() : part.getInputStream()) { + saveFile(fileName, is); + } + attachs.add(attachmentsPath + fileName); + gxmessage.setAttachments(attachs); + } + } + + private String getAttachmentContentId(Part part) throws MessagingException { + String cid = ""; + String[] cids = part.getHeader("Content-ID"); + if (cids != null && !cids[0].isEmpty() && cids[0].startsWith("<") && cids[0].endsWith(">")) { + cid = cids[0].substring(1, cids[0].length() - 1); + } + return cid; + } + + private static final String FILE_INVALID_CHARS = "[\\\\/:*?\"<>|\n\r]"; + private static final Pattern FILE_INVALID_PATTERN = Pattern.compile(FILE_INVALID_CHARS); + private void saveFile(String filename, InputStream input) throws IOException { + filename = FILE_INVALID_PATTERN.matcher(filename).replaceAll("_"); + File file = new File(Paths.get(attachmentsPath, filename).toString()); + try (FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos); BufferedInputStream bis = new BufferedInputStream(input)) { + int aByte; + while ((aByte = bis.read()) != -1) { + bos.write(aByte); + } + bos.flush(); + } catch (IOException e) { + throw new IOException("Error while writing the file", e); + } + } + + public String getNextUID() throws GXMailException { + try { + if (lastReadMessage == numOfMessages) throw new GXMailException("No messages to receive", MAIL_NoMessages); - - int messageNum = lastReadMessage +1; + + int messageNum = lastReadMessage + 1; return emailFolder.getUID(emailFolder.getMessage(messageNum)); - } - catch (MessagingException e) - { - log (e.getMessage()); + } catch (MessagingException e) { + log(e.getMessage()); throw new GXMailException(e.getMessage(), MAIL_ServerRepliedErr); - } + } } - - public int getMessageCount() throws GXMailException - { - try - { - if (readSinceLast) + + public int getMessageCount() throws GXMailException { + try { + if (readSinceLast) return emailFolder.getNewMessageCount(); return emailFolder.getMessageCount(); - } - catch (MessagingException e) - { - log (e.getMessage()); + } catch (MessagingException e) { + log(e.getMessage()); throw new GXMailException(e.getMessage(), MAIL_ServerRepliedErr); } } - public void setAttachmentsPath(String _attachmentsPath) - { + public void setAttachmentsPath(String _attachmentsPath) { attachmentsPath = _attachmentsPath.trim(); - if (!attachmentsPath.equals("")) - { + if (!attachmentsPath.equals("")) { this.downloadAttachments = true; - } - if(!attachmentsPath.equals("") && !attachmentsPath.endsWith(File.separator))attachmentsPath += File.separator; + } + if (!attachmentsPath.equals("") && !attachmentsPath.endsWith(File.separator)) attachmentsPath += File.separator; } - - private void log(String text) - { + + private void log(String text) { logger.debug(text); } -} \ No newline at end of file +}