JavaMail从字符串发送邮件附件 – 编码UTF-8

我的应用程序必须发送一个文本文件,它首先必须生成一个String。 该文本包含非ASCII符号,所以我希望它是UTF-8。 我已经尝试了很多变种,但我收到的所有附件都是一些问号。 而且,当我发送与邮件正文相同的文本时,它可以正常工作。

以下是生成带附件的MimeBodyPart的代码行:

String attachment = "Привет"; messageBodyPart.setContent(new String(attachment.getBytes("UTF-8"), "UTF-8"),"text/plain; charset=UTF-8"); 

我也尝试使用没有任何变换的字符串,只使用字节,现在,如你所见,我试图从字节生成一个字符串…

我究竟做错了什么? (我确实记得在另一个项目中这样做,但是我不再能够访问它的源代码)。

先谢谢你。 提莫菲。

UPDATE

阅读完回复后,经过一些不成功的试验后,我认为最好发布我的邮件代码。 我有Mailer类,它负责邮件发送,其他类只能调用它的静态sendMessage()方法来发送消息。 这一切都在Google App Engine上运行。

 public static void sendMessage(String to, String subject, String msgBody, String attachment) throws AddressException, MessagingException { Properties props = new Properties(); Session mailSession = Session.getDefaultInstance(props, null); Message msg = new MimeMessage(mailSession); String email = "bla-bla-bla"; // userService.getCurrentUser().getEmail(); msg.setFrom(new InternetAddress(email)); msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); InternetAddress[] addresses = { new InternetAddress("bla-bla-bla") }; msg.setReplyTo(addresses); msg.setSubject(subject); Calendar cal = Calendar.getInstance(); String fileName = cal.get(Calendar.YEAR) + "_" + cal.get(Calendar.MONTH) + "_" + cal.get(Calendar.DAY_OF_MONTH) + "_" + cal.get(Calendar.HOUR_OF_DAY) + "_" + cal.get(Calendar.MINUTE) + "_" + cal.get(Calendar.SECOND) + "_" + cal.get(Calendar.MILLISECOND) + ".txt"; // create the message part MimeBodyPart messageBodyPart = new MimeBodyPart(); // fill message // Here we should have the msgBody. // Sending attachment contents for debugging only. messageBodyPart.setText(attachment + " - 4", "UTF-8", "plain"); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart); MimeBodyPart att = new MimeBodyPart(); att.setText(attachment, "UTF-8", "plain"); att.addHeader("Content-Type", "text/plain; charset=UTF-8"); att.setFileName(fileName); multipart.addBodyPart(att); // Put parts in message msg.setContent(multipart); Transport.send(msg); } 

在另一个类中调用此东西的行是:

 Mailer.sendMessage("mymail@example.com", "Test", "No body", "Привет, Я кусок текста"); 

奇怪的是,邮件的原始来源是(忽略看似无关的标题):

 Message-ID:  Date: Sat, 12 Feb 2011 11:21:01 +0000 Subject: Pages From: mymail@example.com To: mymail@example.com Content-Type: multipart/mixed; boundary=00163662e7107ccbd4049c1402fa --00163662e7107ccbd4049c1402fa Content-Type: text/plain; charset=KOI8-R; format=flowed; delsp=yes Content-Transfer-Encoding: base64 8NLJ18XULCDxIMvV08/LINTFy9PUwSAtIDQNCg== --00163662e7107ccbd4049c1402fa Content-Type: text/plain; charset=US-ASCII; name="2011_1_12_11_21_1_691.txt" Content-Disposition: attachment; filename="2011_1_12_11_21_1_691.txt" Content-Transfer-Encoding: base64 Pz8/Pz8/LCA/ID8/Pz8/ID8/Pz8/Pw== --00163662e7107ccbd4049c1402fa-- 

我只是不明白,为什么charsets与我想要设置的不同,以及它们来自哪里。

将内容类型设置为application/octet-stream

 MimeBodyPart attachmentPart = new MimeBodyPart(); try { DataSource ds = new ByteArrayDataSource(attachment.getBytes("UTF-8"), "application/octet-stream"); attachmentPart = new MimeBodyPart(); attachmentPart.setDataHandler(new DataHandler(ds)); } catch (Exception e) { Logger.getLogger("Blina").log(Level.SEVERE, Misc.getStackTrace(e)); } attachmentPart.setFileName(fileName); multipart.addBodyPart(attachmentPart); // Put parts in message msg.setContent(multipart); 

有类似的情况,下面的代码解决了它:

 MimeBodyPart att = new MimeBodyPart(); att.setFileName(MimeUtility.encodeText(fileName)); 

这是我用来发送文件的示例代码(无论编码或数据结构如何)。

 BodyPart fileBodyPart = new MimeBodyPart(); fileBodyPart.setDataHandler(new DataHandler(fileDataSource)); fileBodyPart.setFileName(attachment.getName()); fileBodyPart.setHeader("Content-Type", fileDataSource.getContentType()); fileBodyPart.setHeader("Content-ID", attachment.getName()); fileBodyPart.setDisposition(Part.INLINE); 

其中fileDataSourcejavax.activation.DataSource (文本文件将在此处),以及fileBodyPart.setDisposition(Part.INLINE);PART.INLINE表示数据源与消息体内联,就像HTML电子邮件一样, PART.ATTACHMENT表示数据源是附件)。

希望这可以帮助。

如果问题出在文件名中,而不是在正文中,则以下代码在我的(希伯来语)案例中有所帮助:

 MimeBodyPart attachment = new MimeBodyPart(); attachment.setFileName(MimeUtility.encodeText(filename, "UTF-8", null)); 

尝试一下:

 String attachment = "Привет"; DataSource ds = new ByteArrayDataSource(attachment, "text/plain; charset=UTF-8"); messageBodyPart.setDataHandler(new DataHandler(ds)); 

更新:(完整示例)

 import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.Session; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.util.ByteArrayDataSource; public class Main { public static void main(String[] args) throws Exception { String attachment = "Привет"; DataSource ds = new ByteArrayDataSource(attachment, "text/plain; charset=UTF-8"); MimeBodyPart attachmentPart = new MimeBodyPart(); attachmentPart.setDataHandler(new DataHandler(ds)); MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setText("Hello this is some text"); MimeMultipart mp = new MimeMultipart("mixed"); mp.addBodyPart(bodyPart); mp.addBodyPart(attachmentPart); MimeMessage msg = new MimeMessage((Session)null); msg.setContent(mp); msg.writeTo(System.out); } } 

输出:

 Message-ID: <1439781957.1.1297366787857.JavaMail.dnault@dnault.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_0_1579321858.1297366787792" ------=_Part_0_1579321858.1297366787792 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hello this is some text ------=_Part_0_1579321858.1297366787792 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 0J/RgNC40LLQtdGC ------=_Part_0_1579321858.1297366787792-- 

这有效:

  MimeMessage msg = new MimeMessage(session); msg.setFrom(sendFrom); msg.setSubject(subject, "utf-8"); msg.setSentDate(new Date()); // create and fill the first message part MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setContent(message,"text/plain; charset=UTF-8"); // mbp1.setContent(message,"text/html; charset=UTF-8"); // with this the attachment will fail // create the Multipart and its parts to it Multipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); if (attachment!=null){ // Part two is attachment MimeBodyPart mbp2 = new MimeBodyPart(); mbp2 = new MimeBodyPart(); DataSource ds = null; try { ds = new ByteArrayDataSource(attachment.getBytes("UTF-8"), "application/octet-stream"); } catch (IOException e) { e.printStackTrace(); } mbp2.setDataHandler(new DataHandler(ds)); mbp2.addHeader("Content-Type", "text/plain; charset=\"UTF-8\""); mbp2.addHeader("Content-Transfer-Encoding", "base64"); mbp2.setFileName("attachment.txt"); mbp2.setDisposition(Part.ATTACHMENT); mp.addBodyPart(mbp2); } // add the Multipart to the message msg.setContent(mp); msg.saveChanges(); // send the message Transport.send(msg); 

还有一种可能性:

 String attachment = "älytöntä"; MimeBodyPart part = new MimeBodyPart(); part.setText(attachment, "UTF-8"); part.setDisposition("attachment"); part.setFileName("attachment.txt"); part.setHeader("Content-Transfer-Encoding", "base64"); part.setHeader("Content-type", "text/plain; charset=utf-8");