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

Xamarin Essentials添加邮件附件抛出System.InvalidOperationException问题求助

问题根源分析

这个问题我之前帮同事排查过好几次,核心问题基本都是Android 7.0+的文件URI访问限制和FileProvider配置缺失导致的——你虽然能读写自己应用的私有文件,但邮件应用没有权限直接访问这些路径,所以触发了System.InvalidOperationException。Xamarin.Essentials的Email API在处理附件时依赖系统的文件共享机制,没配置的话自然会报错。

解决步骤(针对Android平台)

1. 配置AndroidManifest.xml

在项目的AndroidManifest.xml的<application>节点内添加FileProvider的配置:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  • authorities要确保是你的应用包名加上.fileprovider(比如com.yourcompany.yourapp.fileprovider),${applicationId}会自动替换为你的项目包名。
  • exported必须设为false,因为FileProvider不需要对外公开;grantUriPermissions设为true,允许临时授权邮件应用访问文件。

2. 创建文件共享路径配置

在Android项目的Resources/xml目录下新建file_paths.xml文件(没有xml目录就手动创建一个),根据你使用的存储目录选择对应的节点:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 对应FileSystem.CacheDirectory(应用私有缓存目录) -->
    <cache-path name="app_cache" path="." />
    <!-- 对应System.Environment.SpecialFolder.LocalApplicationData(应用私有文件目录) -->
    <files-path name="app_files" path="." />
</paths>

path="."表示共享该目录下的所有文件和子目录,你也可以指定具体子路径缩小共享范围。

3. 修改代码:用Content URI传递附件

不要直接把私有文件路径传给EmailAttachment,而是通过FileProvider生成可共享的content://格式URI:

using AndroidX.Core.Content;
using Java.IO;

// 假设你的文件路径是filePath
var targetFile = new File(filePath);
var contentUri = FileProvider.GetUriForFile(
    Android.App.Application.Context,
    $"{Android.App.Application.Context.PackageName}.fileprovider",
    targetFile
);

// 构造邮件并添加附件
var emailMessage = new EmailMessage
{
    Subject = "附件测试邮件",
    Body = "这是带附件的测试内容",
    To = new List<string> { "test@example.com" },
    Attachments = new List<EmailAttachment>
    {
        new EmailAttachment(contentUri.ToString())
    }
};

await Email.ComposeAsync(emailMessage);

注意:如果项目还没引用AndroidX.Core NuGet包,先在NuGet管理器里安装它。

额外检查点
  • 确认文件存在:在添加附件前用File.Exists(filePath)验证,避免因文件不存在触发异常。
  • Android 10+(API 29)及以上不需要申请MANAGE_EXTERNAL_STORAGE权限,因为我们共享的是应用私有文件,FileProvider已经处理了权限逻辑。
  • 如果是iOS平台,只需确保文件放在NSDocumentDirectory或NSTemporaryDirectory,Xamarin.Essentials会自动处理沙箱权限,大概率还是Android的配置问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:29:21