You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MS Graph API发送带EML附件邮件,非Outlook客户端无法预览

问题解决:MS Graph API发送EML附件跨客户端预览异常

核心原因

直接使用FileAttachment携带message/rfc822类型的EML文件时,Graph API可能会丢失MIME类型标记,导致接收端识别为application/octet-stream。而Gmail转发时会重新解析附件内容、修正MIME类型,因此转发后可正常预览。

解决方案

不要用FileAttachment,而是将本地EML文件解析为Graph的Message对象,通过ItemAttachment添加到邮件中。ItemAttachment不仅支持附加Outlook中已有的邮件,也支持附加本地解析生成的Message对象,无需提前在Outlook中存在。这种方式下Graph会正确识别附件的邮件类型,保留message/rfc822的MIME标记,确保跨客户端正常预览。

步骤1:添加JavaMail依赖(用于解析EML)

如果项目未引入JavaMail,需添加依赖(以Maven为例):

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

步骤2:修改代码实现EML解析与附件添加

替换原代码中的附件处理逻辑,改为解析EML为Message对象并使用ItemAttachment:

import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.models.*;
import com.microsoft.graph.serviceclient.GraphServiceClient;
import com.microsoft.graph.users.item.sendmail.SendMailPostRequestBody;

import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Properties;

public class GraphSendMail {
    private static final String USER = "user@domain.be";

    public static void main(String[] args) {
        var credential = new ClientSecretCredentialBuilder()
                .clientId("clientId")
                .tenantId("tenantId")
                .clientSecret("clientSecret")
                .build();

        var client = new GraphServiceClient(credential, "https://graph.microsoft.com/.default");

        var sendMailRequest = new SendMailPostRequestBody();

        Message message = new Message();

        Recipient to = new Recipient();
        to.setEmailAddress(new EmailAddress());
        to.getEmailAddress().setAddress("receiver@gmail.com");
        message.setToRecipients(List.of(to));

        var sender = new Recipient();
        sender.setEmailAddress(new EmailAddress());
        sender.getEmailAddress().setAddress(USER);

        message.setSender(sender);
        message.setFrom(sender);
        message.setSubject("Test mail");

        // 构建HTML邮件正文
        ItemBody body = new ItemBody();
        body.setContentType(BodyType.Html);
        body.setContent("<html><body><h1>Test body</h1></body></html>");
        message.setBody(body);

        String filePath = "C:/pathtofile/attached-mail.eml";
        File emlFile = new File(filePath);
        
        // 将本地EML解析为Graph的Message对象
        Message attachedMessage = parseEmlToGraphMessage(emlFile);
        
        // 创建ItemAttachment关联解析后的邮件
        ItemAttachment attachment = new ItemAttachment();
        attachment.setName("attached-mail.eml");
        attachment.setContentType("message/rfc822");
        attachment.setItem(attachedMessage);

        message.setAttachments(List.of(attachment));

        sendMailRequest.setMessage(message);

        client.users()
                .byUserId(USER)
                .sendMail()
                .post(sendMailRequest);

        System.out.println("Mail sent success");
    }

    // 解析本地EML文件为Graph的Message对象
    private static Message parseEmlToGraphMessage(File emlFile) {
        Message graphMessage = new Message();
        try {
            Session session = Session.getDefaultInstance(new Properties());
            MimeMessage mimeMessage = new MimeMessage(session, new FileInputStream(emlFile));

            // 设置邮件主题
            graphMessage.setSubject(mimeMessage.getSubject());
            
            // 设置发件人
            if (mimeMessage.getFrom() != null && mimeMessage.getFrom().length > 0) {
                Recipient sender = new Recipient();
                EmailAddress senderAddr = new EmailAddress();
                String fromStr = mimeMessage.getFrom()[0].toString();
                senderAddr.setAddress(fromStr.split("<")[1].replace(">", ""));
                senderAddr.setName(fromStr.split("<")[0].trim());
                sender.setEmailAddress(senderAddr);
                graphMessage.setSender(sender);
                graphMessage.setFrom(sender);
            }
            
            // 设置收件人(可按需扩展处理Cc/Bcc)
            if (mimeMessage.getRecipients(javax.mail.Message.RecipientType.TO) != null) {
                List<Recipient> toRecipients = List.of(mimeMessage.getRecipients(javax.mail.Message.RecipientType.TO)).stream()
                        .map(addr -> {
                            Recipient recipient = new Recipient();
                            EmailAddress emailAddr = new EmailAddress();
                            String addrStr = addr.toString();
                            emailAddr.setAddress(addrStr.split("<")[1].replace(">", ""));
                            emailAddr.setName(addrStr.split("<")[0].trim());
                            recipient.setEmailAddress(emailAddr);
                            return recipient;
                        }).toList();
                graphMessage.setToRecipients(toRecipients);
            }
            
            // 设置邮件正文
            ItemBody body = new ItemBody();
            if (mimeMessage.getContentType().contains("text/html")) {
                body.setContentType(BodyType.Html);
                body.setContent(mimeMessage.getContent().toString());
            } else {
                body.setContentType(BodyType.Text);
                body.setContent(mimeMessage.getContent().toString());
            }
            graphMessage.setBody(body);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return graphMessage;
    }
}

关键说明

  • 解析EML时通过JavaMail完整提取原邮件的主题、发件人、收件人、正文等元数据,确保附加的邮件内容完整。
  • ItemAttachment会被Graph标记为message/rfc822类型,Gmail等客户端可直接识别并预览,无需额外处理。

内容的提问来源于stack exchange,提问作者JoeriMJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:25:09