如何使用MemoryStream发送带.txt附件的邮件?
解决方案:用MemoryStream生成文本并通过SendGrid发送无本地文件的邮件附件
嘿,我明白你现在卡在哪了——要把数据库里的Location数据生成文本,用内存流存着直接通过SendGrid发邮件附件,不用先存本地文件对吧?我之前也折腾过类似的需求,给你捋捋具体怎么实现:
第一步:完善MemoryStream写入文本的逻辑
你已经开始用MemoryStream了,核心是要正确把数据写入流,并且写完后重置流的位置到开头,不然后续SendGrid读取的时候会从流的末尾开始,读不到任何内容。这里用StreamWriter来处理文本写入会更方便:
private MemoryStream WriteToTextFile(IEnumerable<Location> locations) { var memoryStream = new MemoryStream(); using (var writer = new StreamWriter(memoryStream, Encoding.UTF8, leaveOpen: true)) { // 可选:先写表头,让文件结构更清晰 writer.WriteLine("ID,名称,纬度,经度"); // 遍历Location数据,按格式写入每一行 foreach (var location in locations) { // 这里用逗号分隔的格式示例,你可以根据需求调整文本格式 writer.WriteLine($"{location.Id},{location.Name},{location.Latitude},{location.Longitude}"); } } // 关键:重置流的位置到起始点,保证后续能读取到完整内容 memoryStream.Position = 0; return memoryStream; }
注意这里StreamWriter的leaveOpen参数设为true,这样在using块结束时不会自动关闭MemoryStream,我们才能完整返回这个流。
第二步:通过SendGrid API发送带内存流附件的邮件
接下来要把MemoryStream转换成SendGrid能识别的附件格式。SendGrid的Attachment类需要把流内容转成Base64字符串,同时指定文件名、媒体类型等关键信息:
using SendGrid; using SendGrid.Helpers.Mail; public async Task SendLocationEmailWithAttachment(string toEmail, IEnumerable<Location> locations) { var apiKey = "你的SendGrid API密钥"; var client = new SendGridClient(apiKey); // 生成存储文本数据的内存流 var textStream = WriteToTextFile(locations); // 将内存流内容转换为Base64字符串(SendGrid附件要求的格式) string base64Content; using (var reader = new StreamReader(textStream)) { var contentBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd()); base64Content = Convert.ToBase64String(contentBytes); // 再次重置流位置,避免后续复用流时出问题 textStream.Position = 0; } // 创建SendGrid附件对象 var attachment = new Attachment { Content = base64Content, Filename = "locations_data.txt", Type = "text/plain", Disposition = "attachment" }; // 构建邮件基础内容 var from = new EmailAddress("your-email@example.com", "你的名称"); var to = new EmailAddress(toEmail); var subject = "最新Location数据文本"; var plainTextContent = "请查收附件中的Location数据文件。"; var htmlContent = "<p>请查收附件中的Location数据文件。</p>"; var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent); msg.Attachments = new List<Attachment> { attachment }; // 发送邮件 var response = await client.SendEmailAsync(msg); // 可以根据response.StatusCode判断发送是否成功 }
关键注意点
- 流的Position重置:每次写入或读取流之后,一定要把
Position设为0,不然后续操作会从当前指针位置开始,导致数据丢失。 - 编码一致性:写入和读取时用相同的编码(比如UTF8),避免出现乱码。
- SendGrid附件参数:
Type要设为正确的媒体类型,普通文本用text/plain,如果是CSV格式可以用text/csv;Disposition设为attachment表示作为附件发送。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

