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

UWP中摄像头拍摄照片作为邮件附件发送后无法打开的问题

解决摄像头照片作为邮件附件无法打开的问题

我太懂这种挫败感了——换了两个SMTP库,邮件都能顺利发出去,但附件图片死活打不开,肯定是图像数据的处理环节出了问题。你怀疑格式问题完全没错,大概率是摄像头捕获的原始帧没有被正确编码为有效的JPEG格式,直接把原始流/字节传出去,附件自然是损坏的。

下面针对你用的两个库分别给出修复方案,先从最核心的图像编码步骤说起:

第一步:先把摄像头捕获的帧转成有效的JPEG数据

摄像头捕获的CapturedPhoto.Frame通常是原始像素格式(比如YUV或者NV12),不是直接可用的JPG流。你需要先把它编码成JPEG格式的字节流,再用来生成附件。这里给你一个通用的转换方法:

private async Task<byte[]> ConvertFrameToJpegBytes(CapturedPhoto photo)
{
    using (var stream = photo.Frame.CloneStream())
    {
        var decoder = await BitmapDecoder.CreateAsync(stream);
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
        
        // 设置编码参数,可根据需求调整质量
        encoder.BitmapTransform.ScaledWidth = decoder.PixelWidth;
        encoder.BitmapTransform.ScaledHeight = decoder.PixelHeight;
        encoder.IsThumbnailGenerated = false;
        encoder.Quality = 80;
        
        await encoder.FlushAsync();
        
        // 重置流位置并读取字节
        stream.Seek(0);
        var bytes = new byte[stream.Size];
        await stream.ReadAsync(bytes.AsBuffer(), (uint)stream.Size, InputStreamOptions.None);
        return bytes;
    }
}

这个方法会把原始帧解码后重新编码为JPEG,确保输出的是有效的JPG字节数据。


针对LightBuzz.SMTP的修改

你原来的代码直接用image.Frame.CloneStream()创建附件,但这个流是原始帧格式,不是JPG。修改成使用上面的转换方法,把JPEG字节转成RandomAccessStreamReference:

private async Task<SmtpResult> SendAlertEmail(List<CapturedPhoto> images)
{
    using (SmtpClient client = new SmtpClient("smtp.gmail.com", 465, true, "mygmail@gmail.com", "myPassword"))
    {
        EmailMessage emailMessage = new EmailMessage();
        emailMessage.Sender.Address = "IoTAlertApp@donotreply.com";
        emailMessage.Sender.Name = "IoT App";
        emailMessage.To.Add(new EmailRecipient("myemail@gmail.com"));
        emailMessage.Subject = "ALERT | MOTION DETECTED";
        emailMessage.Body = "This is an email sent from a UWP app!";

        if (images.Any())
        {
            int imageCount = 1;
            string fileName = $"image_{imageCount}_{DateTime.Now.Ticks}.jpg";
            var jpegBytes = await ConvertFrameToJpegBytes(images[0]);
            
            // 把JPEG字节转成内存流
            using (var stream = new InMemoryRandomAccessStream())
            {
                await stream.WriteAsync(jpegBytes.AsBuffer());
                stream.Seek(0);
                RandomAccessStreamReference reference = RandomAccessStreamReference.CreateFromStream(stream);
                emailMessage.Attachments.Add(new EmailAttachment(fileName, reference));
            }
        }

        images.Clear();
        SmtpResult result = await client.SendMailAsync(emailMessage);
        return result;
    }
}

关键变化:先把原始帧转成JPEG字节,再写入内存流,用这个内存流创建附件引用,确保附件是有效的JPG文件。


针对EASendMailRT的修改

你的代码里传入的byte[] image如果是原始帧数据,那肯定不行。修改成用上面的转换方法生成JPEG字节,再传入:

private async Task Send_Email(CapturedPhoto photo)
{
    String Result = "";
    try
    {
        SmtpMail oMail = new SmtpMail("TryIt");
        SmtpClient oSmtp = new SmtpClient();
        oMail.From = new MailAddress("IoTSquatter@DoNotReply.com");
        oMail.To.Add(new MailAddress("myemail@gmail.com"));
        oMail.Subject = "ALERT | MOTION DETECTED";

        SmtpServer oServer = new SmtpServer("smtp.gmail.com");
        oServer.User = "myemail@gmail.com";
        oServer.Password = "password"; // 注意:Gmail建议用应用专用密码,不要用明文账号密码
        oServer.Port = 465;
        oServer.ConnectType = SmtpConnectType.ConnectSSLAuto;

        // 先把捕获的照片转成JPEG字节
        var jpegBytes = await ConvertFrameToJpegBytes(photo);
        Attachment oAttachment = oMail.AddAttachment("testImage.jpg", jpegBytes);
        
        string contentID = "test001@host";
        oAttachment.ContentID = contentID;
        oMail.HtmlBody = $"<html><body>this is an <img src=\"cid:{contentID}\"> embedded picture.</body></html>";

        await oSmtp.SendMailAsync(oServer, oMail);
        Result = "Email was sent successfully!";
    }
    catch (Exception ep)
    {
        Result = String.Format("Failed to send email with the following error: {0}", ep.Message);
    }
}

另外提醒:Gmail现在不允许直接用账号密码登录SMTP,建议开启两步验证后使用应用专用密码,否则可能会被拒绝登录。


额外排查步骤

  1. 本地测试编码结果:把转换后的JPEG字节保存到本地文件,看看能不能正常打开。如果本地都打不开,说明编码环节有问题,需要检查ConvertFrameToJpegBytes方法的参数(比如解码器是否正确识别原始帧格式)。
  2. 检查MIME类型:有些SMTP库需要显式指定附件的MIME类型为image/jpeg,如果上面的修改后还是不行,可以尝试给Attachment添加ContentType属性(比如LightBuzz的EmailAttachment有没有ContentType设置项,EASendMailRT的Attachment会默认根据后缀识别,但也可以手动指定)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:57:25