【问题标题】:ImapIdleChannelAdapter doesn't get message contentImapIdleChannelAdapter 没有得到消息内容
【发布时间】:2019-10-23 17:17:26
【问题描述】:

我正在使用此代码从 IMAP 服务器读取邮件:

@EnableIntegration
public class MailIntegration implements HasLogger {

    @Bean
    public ImapIdleChannelAdapter messageChannel(ImapMailReceiver receiver) {
        var receiver = new ImapMailReceiver("imaps://...");
        var adapter = new ImapIdleChannelAdapter(receiver);
        adapter.setOutputChannelName("imapChannel");
        return adapter;
    }

    @ServiceActivator(inputChannel = "imapChannel")
    public void handleMessage(MimeMessage message) {
        getLogger().info("Got message!");

        var subject = message.getSubject();
        getLogger().info("Subject: {}", subject);

        var contentType = message.getContentType();
        getLogger().info("ContentType: {}", contentType);

        var content = message.getContent();
        if (content instanceof String) {
            var text = (String) content;
            getLogger().info("Content: {}", text);
            getLogger().info("Length: {}", text.length());
        } else {
            getLogger().info("Other content: {}", content);
        }
    }
}

如果我发送纯文本电子邮件,处理程序会启动并记录:

INFO : Got message!
INFO : Subject: Lorem ipsum dolor sit amet
INFO : ContentType: text/plain; charset="utf-8"
INFO : Content:
INFO : Length: 0

如果我发送 HTML 电子邮件,处理程序会启动并记录:

INFO : Got message!
INFO : Subject: Lorem ipsum dolor sit amet
INFO : ContentType: text/html; charset="utf-8"
INFO : Content:
INFO : Length: 0

主题是正确的(标题也是如此),但对于普通电子邮件和 HTML 电子邮件,内容始终为空。

另外,我希望收到 HTML 的 multipart 消息,而不仅仅是 text/html 部分。事实上,如果我检查电子邮件客户端中的原始消息,我会看到:

From: Giovanni Lovato <giovanni.lovato@...>
To: Test <test@...>
Subject: Lorem ipsum dolor sit amet
... lots of other header lines ...
Content-type: multipart/alternative; boundary="B_3642854791_1171496246"

> This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

--B_3642854791_1171496246
Content-type: text/plain; charset="UTF-8"
Content-transfer-encoding: quoted-printable

Lorem ipsum dolor sit amet.

--B_3642854791_1171496246
Content-type: text/html; charset="UTF-8"
Content-transfer-encoding: quoted-printable

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
  <p>Lorem ipsum dolor sit amet.</p>
</body>
</html>


--B_3642854791_1171496246--

所以看起来ImapIdleChannelAdapter 已经在提取 HTML 部分并将其传递给处理程序,以及所有原始标题;不过还是没有内容。

我做错了吗?

【问题讨论】:

  • 尝试在ImapMailReceiver 上将simpleContent 设置为truedocs.spring.io/spring-integration/docs/current/reference/html/…。还要确保 ImapMailReceiver 被声明为 bean。不确定您的 messageChannel 配置现在发生了什么。旁注:ChannelAdapter 确实不是 channel - 最好不要混淆自己,也不要将这样的 bean 命名为 messageChannel
  • simpleContent 设置为true 确实有效!该死的令人困惑,“简单的内容”是什么意思?事件 JavaDocs 很难理解。谢谢!

标签: java spring spring-integration imap mime


【解决方案1】:

尝试在ImapMailReceiver 上将simpleContent 设置为truehttps://docs.spring.io/spring-integration/docs/current/reference/html/#mail-inbound

如果为真,邮件正文的内容将按需获取:

@Override
    public Object getContent() throws IOException, MessagingException {
        if (AbstractMailReceiver.this.simpleContent) {
            return super.getContent();
        }
        else {
            return this.content;
        }
    }

而不是急切地获取:

IntegrationMimeMessage(MimeMessage source) throws MessagingException {
        super(source);
        this.source = source;
        if (AbstractMailReceiver.this.simpleContent) {
            this.content = null;
        }
        else {
            Object complexContent;
            try {
                complexContent = source.getContent();
            }
            catch (IOException e) {
                complexContent = "Unable to extract content; see logs: " + e.getMessage();
                AbstractMailReceiver.this.logger.error("Failed to extract content from " + source, e);
            }
            this.content = complexContent;
        }
    }

5.2版本中我们已经介绍过:

/**
 * Configure a {@code boolean} flag to close the folder automatically after a fetch (default) or
 * populate an additional {@link IntegrationMessageHeaderAccessor#CLOSEABLE_RESOURCE} message header instead.
 * It is the downstream flow's responsibility to obtain this header and call its {@code close()} whenever
 * it is necessary.
 * <p> Keeping the folder open is useful in cases where communication with the server is needed
 * when parsing multipart content of the email with attachments.
 * <p> The {@link #setSimpleContent(boolean)} and {@link #setHeaderMapper(HeaderMapper)} options are not
 * affected by this flag.
 * @param autoCloseFolder {@code false} do not close the folder automatically after a fetch.
 * @since 5.2
 */
public void setAutoCloseFolder(boolean autoCloseFolder) {

我相信这个也应该对你有所帮助。

【讨论】:

  • 不确定我是否理解setAutoCloseFolder 方法:设置simpleContent = true 我可以获取电子邮件附件,这是我需要的,但之后我需要手动关闭某些内容吗?如果我设置了这个“自动关闭”标志,我能在处理程序中获取附件吗?
  • 是的,您可以,但您还需要自己关闭一个文件夹。尽管无论如何它都会在您的应用程序结束时关闭。在某些情况下,如果文件夹关闭,我们无法从邮件中获取所有内容。您可能不会考虑simpleContent 是否足以满足您的需求。
  • 查看this issuethis issue了解更多背景信息。
猜你喜欢
  • 1970-01-01
  • 2012-03-09
  • 2017-01-07
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
相关资源
最近更新 更多