Blazor Wasm 发送邮件抛出异常 System.PlatformNotSupportedException: System.Net.Dns:GetHostByName 在此平台上不受支持

Posted

技术标签:

【中文标题】Blazor Wasm 发送邮件抛出异常 System.PlatformNotSupportedException: System.Net.Dns:GetHostByName 在此平台上不受支持【英文标题】:Blazor Wasm sending mail throw exception System.PlatformNotSupportedException: System.Net.Dns:GetHostByName is not supported on this platform 【发布时间】:2021-01-27 06:04:22 【问题描述】:

我正在尝试从 Blazor WASM 应用发送电子邮件,但收到此异常

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常呈现组件:无法发送消息。 System.Net.Mail.SmtpException:无法发送消息。 ---> System.PlatformNotSupportedException:此平台不支持 System.Net.Dns:GetHostByName。 在 System.Net.Sockets.TcpClient..ctor (System.String 主机名,System.Int32 端口) 在:0 在 System.Net.Mail.SmtpClient.SendInternal (System.Net.Mail.MailMessage 消息) in :0 在 System.Net.Mail.SmtpClient.Send (System.Net.Mail.MailMessage 消息) in :0 --- 内部异常堆栈跟踪结束 --- 在 System.Net.Mail.SmtpClient.Send (System.Net.Mail.MailMessage 消息) in :0 在 C:\Users\ismailghedamsi\Source\Repos\MusicSellingPlatformVeille\MusicSellingApp\Client\Pages\ArtistProfile.razor:33 中的 MusicSellingApp.Client.Pages.ArtistProfile.SendMail () [0x000a3] 在 C:\Users\ismailghedamsi\Source\Repos\MusicSellingPlatformVeille\MusicSellingApp\Client\Pages\ArtistProfile.razor:38 中的 MusicSellingApp.Client.Pages.ArtistProfile.OnInitializedAsync () [0x0000f] 在 Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () in :0

这是我的剃须刀文件

@page "/artistProfile"
@inject ILocalStorageService storageService
@using System.Net.Mail
<h2>@(artist == null)</h2>
<UserInfoComponent User="@artist" />

@code
    Artist artist;

    public void SendMail()
    
        try
        
            using (MailMessage mail = new MailMessage())
            
                mail.From = new MailAddress("mymail@gmail.com");
                mail.To.Add("mymail@gmail.com");
                mail.Subject = "Sending mail";
                mail.Body = "<h2>this is a mail body</h2>";
                mail.IsBodyhtml = true;
                using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                
                    smtp.Credentials = new System.Net.NetworkCredential("mymail@gmail.com", "mypassword");
                    smtp.EnableSsl = true;
                    smtp.Send(mail);
                
            
        
        catch (Exception)
        
            throw;
        
    
    protected override async Task OnInitializedAsync()
    
        SendMail();
        artist = await storageService.GetItemAsync<Artist>("loggedUser");
    


相同的 c# 代码正在控制台应用程序上运行

【问题讨论】:

浏览器网页如何发送电子邮件?这是某种新的 HTML5 API 吗?!如果是这样,那么那些 W3C 的人就不会懈怠了! Blazor 允许直接在浏览器上执行 c# 代码 不错,尝试在浏览器上执行这段C#代码Process.Start("Notepad")会启动一个新的记事本进程吗? 你的错误信息很干净 【参考方案1】:

尽管 Blazor (wasm) 可以直接在浏览器上运行 C# 代码,但它受到浏览器功能的限制,发送电子邮件不是浏览器可以做的事情。在这种情况下,通常会抛出 PlatformNotSupportedException,否则您会在 Visual Studio CA1416: Validate platform compatibility 上收到警告。在这种情况下,替代方法是调用发送电子邮件的服务器 API。

【讨论】:

【参考方案2】:

@Guilherme 的回答大部分是正确的,因为 Blazor (WASM) 不能使用浏览器平台不支持的类,如 SmtpClient。然而,这并不是故事的全部。有一种解决方法可用于非常基本的电子邮件需求,它利用了使用“mailto:”锚链接结合注入 IJSRuntime 的老式技术。

让我提供一些示例代码,以帮助下一个遇到这篇文章的开发人员。请记住,此技术使用查询字符串,而 MAILTO 函数的限制约为 2000 个字符。超过此限制可能会导致邮件无法在用户的默认邮件应用中打开。

通过按钮单击或其他触发器,调用视图模型(或 c# 代码)中的函数:

protected void SendLocalEmail(string toEmailAddress, string subject, string body)

    JsRuntime.InvokeAsync<object>("blazorExtensions.SendLocalEmail",
      new object[]  toEmailAddress, subject, body );

然后,在您的 wwwroot 文件夹中,您应该有一个相应的 .js 文件(即 GlobalFunctions.js),其中包含相应的 javascript SendLocalEmail() 函数,例如:

window.blazorExtensions = 
  SendLocalEmail: function (mailto, subject, body) 
    var link = document.createElement('a');
    var uri = "mailto:" + mailto + "?";
    if (!isEmpty(subject)) 
        uri = uri + "subject=" + subject;
    

    if (!isEmpty(body)) 
        if (!isEmpty(subject))  // We already appended one querystring parameter, add the '&' separator
            uri = uri + "&"
        

        uri = uri + "body=" + body;
    

    uri = encodeURI(uri);
    uri = uri.substring(0, 2000); // Avoid exceeding querystring limits.
    console.log('Clicking SendLocalEmail link:', uri);

    link.href = uri;
    document.body.appendChild(link); // Needed for Firefox
    link.click();
    document.body.removeChild(link);
  
;

function isEmpty(str) 
  return (!str || str.length === 0);

最后,确保在 index.html 文件中包含对 .js 文件的引用(也在 wwwroot 文件夹中):

<script src="GlobalFunctions.js"></script>

我将上面的脚本引用放在这一行下面:

<script>navigator.serviceWorker.register('service-worker.js');</script>

【讨论】:

你这行不通。如果我在 javascript 函数中首先发出警报,它不会出现,所以我知道它没有被调用

以上是关于Blazor Wasm 发送邮件抛出异常 System.PlatformNotSupportedException: System.Net.Dns:GetHostByName 在此平台上不受支持的主要内容,如果未能解决你的问题,请参考以下文章

如何绕过 blazor wasm 路由系统并调用服务器

IdentityServerBuilderConfigurationExtension 中的 Blazor WASM 托管身份验证空引用异常

C#:如何在 Blazor Wasm 托管中将动态 Razor 组件从服务器发送到客户端?

Blazor WASM AzureAD IdentityServer 导致 AADSTS90023:公共客户端无法发送客户端密码

Blazor 客户端 (WASM) 应用程序洞察

如何在 ASP .NET Core Web API 中映射回退,以便 Blazor WASM 应用程序仅拦截未发送到 API 的请求