SubEthaSMTP服务器扩展IMAP类邮件功能及MimeMessage操作异常问题咨询
Let's break down your problem and walk through the solutions step by step:
First: Why Are Those Exceptions Happening?
Looking at your code and logs, two key issues are causing the errors:
message.getFolder()returnsnull: TheMimeMessageyou're creating directly from the SMTP input stream isn't associated with any IMAP folder. This object is just a parsed representation of the email content, not tied to a storage system that supports IMAP folder operations. CastingnulltoIMAPFolderthrows an uncaught exception, which triggers your genericcatch (Exception e)block.getMessageID()isn't actually failing: Your log shows the Message-ID (<472353602.8.1645952362453@DESKTOP-FFJA5IP>) is printed successfully before the exception. The error comes from the folder code that follows, not thegetMessageID()call itself.
Fix the Immediate Exception
First, let's clean up your EmailContentServiceImpl to remove the invalid folder code and preserve useful error context:
@Service public class EmailContentServiceImpl implements EmailContentService { @Override public MimeMessage convertToMimeMessage(InputStream data) throws MessagingException { Session session = Session.getDefaultInstance(new Properties()); return new MimeMessage(session, data); // No need for redundant try/catch here } @Override public ReceivedEmail extractReceivedEmail(InputStream data) throws Exception { ReceivedEmail receivedEmail = new ReceivedEmail(); try { MimeMessage message = this.convertToMimeMessage(data); receivedEmail.setSubject(message.getSubject()); receivedEmail.setSenderAddress(InternetAddress.toString(message.getFrom())); // This works fine - preserve the Message-ID for later storage String messageId = message.getMessageID(); System.out.println("Message ID: " + messageId); receivedEmail.setMessageId(messageId); // Remove the invalid IMAPFolder code - this message isn't tied to any folder yet return receivedEmail; } catch (MessagingException e) { // Wrap the original exception to retain debugging info throw new Exception("Failed to parse incoming email content", e); } } }
To Add IMAP Features (Folder Management, Marking Emails, Etc.)
SubEthaSMTP only handles SMTP email reception - it doesn't provide IMAP server functionality. To implement the features you want (folder listing, marking emails as read, forwarding, etc.), you need to pair it with an IMAP-compatible mail storage system and server.
The easiest way to do this is to use an embedded open-source mail server like GreenMail, which supports both SMTP and IMAP out of the box. Here's how to integrate it:
Step 1: Add GreenMail Dependency (Maven)
<dependency> <groupId>com.icegreen</groupId> <artifactId>greenmail</artifactId> <version>2.0.0</version> </dependency>
Step 2: Configure GreenMail + SubEthaSMTP
Replace your existing SMTPServerConfig with this setup to route incoming SMTP emails to GreenMail's IMAP storage:
@Configuration public class MailServerConfig { @Bean public GreenMail greenMail() { // Start GreenMail with SMTP, IMAP, and POP3 support GreenMail greenMail = new GreenMail(ServerSetupTest.ALL); // Create a test user for your domain greenMail.setUser("info@marketingchris.com", "your-password-here"); greenMail.start(); return greenMail; } @Bean public SMTPServer smtpServer(GreenMail greenMail) { SimpleMessageListener listener = new SimpleMessageListener() { @Override public boolean accept(String from, String recipient) { return recipient != null && recipient.endsWith("@marketingchris.com"); } @Override public void deliver(String from, String recipient, InputStream data) throws IOException { try { // Parse the incoming email and store it in GreenMail's IMAP inbox Session session = Session.getInstance(new Properties()); MimeMessage message = new MimeMessage(session, data); Store imapStore = greenMail.getImap().createStore(); imapStore.connect(recipient, "your-password-here"); Folder inbox = imapStore.getFolder("INBOX"); inbox.open(Folder.READ_WRITE); inbox.appendMessages(new MimeMessage[]{message}); inbox.close(false); imapStore.close(); } catch (Exception e) { e.printStackTrace(); } } }; return SMTPServer.port(25001) .simpleMessageListener(listener) .requireAuth(true) .authenticationHandlerFactory(new EasyAuthenticationHandlerFactory(new SimpleAuthValidatorImpl())) .hostName("localhost") .enableTLS(true) .build(); } }
Step 3: Implement IMAP Features
Create a service class to handle IMAP operations like folder management, marking emails as read, etc.:
@Service public class ImapMailService { private final GreenMail greenMail; public ImapMailService(GreenMail greenMail) { this.greenMail = greenMail; } // List all root folders public List<String> listRootFolders(String username, String password) throws MessagingException { Store store = greenMail.getImap().createStore(); store.connect(username, password); Folder[] rootFolders = store.getDefaultFolder().list(); List<String> folderNames = new ArrayList<>(); for (Folder folder : rootFolders) { folderNames.add(folder.getFullName()); } store.close(); return folderNames; } // Mark an email as read public void markEmailAsRead(String username, String password, String folderName, int messageIndex) throws MessagingException { Store store = greenMail.getImap().createStore(); store.connect(username, password); Folder folder = store.getFolder(folderName); folder.open(Folder.READ_WRITE); Message message = folder.getMessage(messageIndex); message.setFlag(Flags.Flag.SEEN, true); folder.close(false); store.close(); } // Create a custom folder (e.g., "Sent", "Trash") public void createFolder(String username, String password, String folderName) throws MessagingException { Store store = greenMail.getImap().createStore(); store.connect(username, password); Folder rootFolder = store.getDefaultFolder(); Folder newFolder = rootFolder.getFolder(folderName); if (!newFolder.exists()) { newFolder.create(Folder.HOLDS_MESSAGES); } store.close(); } // Copy an email to another folder (e.g., Sent or Trash) public void copyEmailToFolder(String username, String password, String sourceFolder, int messageIndex, String targetFolder) throws MessagingException { Store store = greenMail.getImap().createStore(); store.connect(username, password); Folder source = store.getFolder(sourceFolder); source.open(Folder.READ_ONLY); Folder target = store.getFolder(targetFolder); if (!target.exists()) { target.create(Folder.HOLDS_MESSAGES); } target.open(Folder.READ_WRITE); source.copyMessages(new Message[]{source.getMessage(messageIndex)}, target); source.close(false); target.close(false); store.close(); } }
Key Takeaway
SubEthaSMTP is only for receiving emails via SMTP. To add IMAP functionality, you need a mail storage system that supports IMAP operations. GreenMail is a lightweight, embeddable solution that handles both SMTP and IMAP, making it perfect for your use case.
内容的提问来源于stack exchange,提问作者Christian Ibanibo

