使用C#创建ICS文件并发送带附件日历邮件:附件丢失求助
解决ICS日历附件丢失的邮件发送问题
嘿,我明白你现在急着解决这个问题——邮件能收到但ICS附件丢了,大概率是在生成ICS内容或者添加附件的环节踩了坑。我帮你梳理下关键问题点,再给你一个能直接用的修正版代码:
修正后的完整代码
public IHttpActionResult Cal(calendar objApptEmail) { try { // 生成符合iCalendar标准的ICS内容,这是客户端能识别的核心 string icsContent = @"BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Your Company//EN METHOD:REQUEST BEGIN:VEVENT UID:" + Guid.NewGuid().ToString() + @" DTSTAMP:" + DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ") + @" DTSTART:" + objApptEmail.StartDate.ToUniversalTime().ToString("yyyyMMddTHHmmssZ") + @" DTEND:" + objApptEmail.EndDate.ToUniversalTime().ToString("yyyyMMddTHHmmssZ") + @" SUMMARY:" + EscapeIcsText(objApptEmail.Subject) + @" DESCRIPTION:" + EscapeIcsText(objApptEmail.Description) + @" LOCATION:" + EscapeIcsText(objApptEmail.Location) + @" ORGANIZER;CN=Your Display Name:mailto:your-sender-email@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;CN=Attendee Name:mailto:" + objApptEmail.AttendeeEmail + @" END:VEVENT END:VCALENDAR"; // 将ICS内容写入内存流,注意写完后要重置流位置 using (MemoryStream ms = new MemoryStream()) using (StreamWriter sw = new StreamWriter(ms, System.Text.Encoding.UTF8)) { sw.Write(icsContent); sw.Flush(); ms.Seek(0, SeekOrigin.Begin); // 重中之重:把流指针移到开头,否则附件会是空的 // 构建邮件 using (MailMessage msg = new MailMessage()) using (SmtpClient smtp = new SmtpClient("your-smtp-server", 587)) { msg.From = new MailAddress("your-sender-email@example.com", "Your Display Name"); msg.To.Add(objApptEmail.AttendeeEmail); msg.Subject = objApptEmail.Subject; msg.Body = "请查看附件中的日历邀请"; // 添加ICS附件,设置正确的MIME类型 Attachment icsAttachment = new Attachment(ms, "Meeting-Invite.ics", "text/calendar"); // 标记为附件而非内联内容 icsAttachment.ContentDisposition.Inline = false; msg.Attachments.Add(icsAttachment); // 配置SMTP服务器(根据你的实际环境调整) smtp.Credentials = new System.Net.NetworkCredential("your-smtp-username", "your-smtp-password"); smtp.EnableSsl = true; // 发送邮件 smtp.Send(msg); } } return Ok("日历邀请已成功发送!"); } catch (Exception ex) { return InternalServerError(ex); } } // 辅助方法:处理ICS文本中的特殊字符,避免格式错误 private string EscapeIcsText(string text) { if (string.IsNullOrEmpty(text)) return string.Empty; return text.Replace("\\", "\\\\") .Replace(";", "\\;") .Replace(",", "\\,") .Replace("\n", "\\n"); }
关键注意点(这是你之前可能遗漏的地方)
- ICS标准必须合规:
必须包含VCALENDAR和VEVENT核心结构,UID要唯一(用Guid生成就很稳妥),时间字段必须是UTC格式的yyyyMMddTHHmmssZ,METHOD:REQUEST是让邮件客户端识别为「邀请」的关键标识。 - 流位置一定要重置:
用StreamWriter写完内容后,流的指针会停在末尾,必须用ms.Seek(0, SeekOrigin.Begin)把指针移到开头,否则邮件客户端读取附件时会读到空内容。 - MIME类型不能错:
附件的MIME类型必须设置为text/calendar,不能用默认的application/octet-stream,否则客户端可能无法识别这是日历文件,甚至直接丢弃。 - 特殊字符要转义:
ICS内容里的换行、分号、逗号等特殊字符必须转义,否则会破坏ICS格式,导致客户端解析失败——我加了EscapeIcsText辅助方法来处理这个问题。
内容的提问来源于stack exchange,提问作者Raja sekhar
相关产品推荐
相关产品推荐

