655 lines
79 KiB
HTML
655 lines
79 KiB
HTML
<!DOCTYPE html>
|
|
<!-- saved from url=(0126)https://www.exfabrica.io/en/blog/how-to-securely-send-emails-via-gmail-using-oauth2-in-csharp-dotnet-a-step-by-step-guide.html -->
|
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="description" content="exFabrica develops in an agile context web and mobile solutions without compromising on quality. Our teams of experts deliver, on time, maintainable and efficient code vector of business value."><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><meta property="og:site_name" content="exFabrica - Bespoke digital product factory"><meta property="og:url" content="https://www.exfabrica.io"><link rel="apple-touch-icon-precomposed" sizes="57x57" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-57x57.png"><link rel="apple-touch-icon-precomposed" sizes="60x60" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-60x60.png"><link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-72x72.png"><link rel="apple-touch-icon-precomposed" sizes="76x76" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-76x76.png"><link rel="apple-touch-icon-precomposed" sizes="114x114" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-114x114.png"><link rel="apple-touch-icon-precomposed" sizes="120x120" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-120x120.png"><link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-144x144.png"><link rel="apple-touch-icon-precomposed" sizes="152x152" href="https://www.exfabrica.io/src/assets/imgs/favicons/apple-touch-icon-152x152.png"><link rel="icon" type="image/png" href="https://www.exfabrica.io/src/assets/imgs/favicons/favicon-196x196.png" sizes="196x196"><link rel="icon" type="image/png" href="https://www.exfabrica.io/src/assets/imgs/favicons/favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/png" href="https://www.exfabrica.io/src/assets/imgs/favicons/favicon-32x32.png" sizes="32x32"><link rel="icon" type="image/png" href="https://www.exfabrica.io/src/assets/imgs/favicons/favicon-16x16.png" sizes="16x16"><link rel="icon" type="image/png" href="https://www.exfabrica.io/src/assets/imgs/favicons/favicon-128x128.png" sizes="128x128"><link href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/global.css" type="text/css" rel="stylesheet"><link href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/blog.css" type="text/css" rel="stylesheet"><link href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/print.8.css" type="text/css" rel="stylesheet" media="print"><link rel="preload" href="https://www.exfabrica.io/visualIdentity/fonts/Outfit-VariableFont_wght.ttf" as="font" type="font/ttf" crossorigin=""><style>footer{border-top:1px solid rgba(var(--neutral_200));text-align:center}footer .mainWrapper{display:flex;align-items:center;flex-wrap:wrap;gap:24px;padding:32px 24px;justify-content:space-between}footer small{text-align:right;white-space:nowrap;font-size:1rem}footer .carbonbadge{display:flex}</style><style>.mainHeader{position:fixed;z-index:2;top:0;width:100%;background-color:rgba(var(--neutral_0));color:rgba(var(--neutral_400));transition:background-color .35s,color .35s,border .35s;border-bottom:1px solid rgb(var(--neutral_200))}.mainHeader .skipLink{display:block;width:100%;text-align:center;position:absolute;height:1px;clip-path:inset(50%);background-color:rgb(var(--neutral_0));padding:16px;border-radius:0}.mainHeader .skipLink:focus{position:relative;height:auto;clip-path:none;outline-offset:-4px}.mainHeader .logo{display:flex;align-items:center;padding:8px 0}.mainHeader .logo a{display:block;background:url(../../src/visualIdentity/logo/logo-exFabrica-light.svg) center/contain no-repeat;width:11.25rem;aspect-ratio:2.98/1}.mainHeader .mainWrapper{display:flex;align-items:center;justify-content:space-between;column-gap:32px;height:5.1875rem}.mainHeader .menuItems{display:flex;align-items:center;column-gap:16px}.mainHeader .menuItems a{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;color:inherit;padding:8px 16px;border-radius:8px;font-weight:600;transition:color 0s .1s;position:relative}.mainHeader .menuItems a:before{position:absolute;content:"";display:block;width:100%;height:100%;background-color:rgb(var(--tertiary));border-radius:8px;z-index:-1;clip-path:inset(50% 50% 50% 50% round 8px);transition:clip-path .2s ease-out}.mainHeader .menuItems a:hover:before{clip-path:inset(0% 0% 0% 0% round 8px)}.mainHeader .menuItems a.selected{color:rgb(var(--neutral_0));background-color:rgb(var(--primary));text-decoration:underline}.mainHeader .menuItems a:focus-visible{outline:1px dashed rgb(var(--primary))}@media screen and (min-width: 62.5rem){.mainHeader .menuWrapper{display:flex;column-gap:16px;margin-right:8px}.mainHeader .menuItems{display:flex}.mainHeader .toggle-btn{display:none}.mainHeader.reversed{background-color:rgba(0,0,0,0);border-bottom:none}.mainHeader.reversed .navigation .menuItems{color:rgb(var(--neutral_0))}.mainHeader.reversed .navigation .menuItems a img{filter:url(#neutral_0)}.mainHeader.reversed .navigation .menuItems a:hover{color:rgb(var(--neutral_400))}.mainHeader.reversed .navigation .menuItems a:hover img{filter:url(#neutral_400)}.mainHeader.reversed .navigation .menuItems a:hover:before{background-color:rgb(var(--tertiary))}.mainHeader.reversed .navigation .menuItems a:focus-visible{outline:1px dashed rgb(var(--neutral_0))}.mainHeader.reversed .navigation .menuItems a.selected{color:rgb(var(--neutral_400));background-color:rgb(var(--neutral_0))}.mainHeader.reversed .navigation .menuItems a.selected img{filter:url(#neutral_400)}.mainHeader.reversed button.primary{background-color:rgb(var(--neutral_0));color:rgb(var(--neutral_400))}.mainHeader.reversed button.primary:hover{color:rgba(var(--neutral_400));background-color:rgb(var(--tertiary))}.mainHeader.reversed button:focus-visible{outline-color:rgb(var(--neutral_0))}.mainHeader.reversed .logo{filter:brightness(0) invert(1)}.mainHeader.reversed .logo a:focus-visible{outline:1px dashed rgb(var(--neutral_0))}}@media screen and (max-width: 62.4375rem){.mainHeader .toggle-btn{display:inline-block;position:relative;width:2.5rem;height:2.5rem;padding:0.5rem 0.3125rem;background-color:rgba(255,255,255,0);box-shadow:rgba(0,0,0,0) 0 3px 8px;border-radius:8px;transition:background-color .2s,box-shadow .2s}.mainHeader .toggle-btn:focus,.mainHeader .toggle-btn:hover{background-color:rgba(255,255,255,.08);box-shadow:rgba(0,0,0,.24) 0 3px 8px}.mainHeader .ico-burger,.mainHeader .ico-burger:after,.mainHeader .ico-burger:before{position:absolute;width:calc(2.5rem - 1.25rem);height:.125rem;transition:transform .15s;background-color:rgb(var(--neutral_400));display:block}.mainHeader .ico-burger{top:50%;left:0.625rem;display:block;margin-top:-1px;overflow:visible}.mainHeader .ico-burger:after,.mainHeader .ico-burger:before{content:""}.mainHeader .ico-burger:before{top:calc(0.375rem*-1)}.mainHeader .ico-burger:after{top:0.375rem}.mainHeader .menuWrapper{background-color:rgba(var(--neutral_0));border-top:1px solid rgb(var(--neutral_200));position:fixed;top:5.1875rem;bottom:0;left:0;right:0;clip-path:ellipse(25% 0% at 50% 0%);transition:clip-path .5s,visibility 0s .5s;padding:24px;display:grid;visibility:hidden;align-items:center}.mainHeader .menuItems{position:relative;opacity:0;overflow:auto;max-height:100%;transition:opacity .7s .1s;flex-direction:column;row-gap:32px;grid-area:1/1/2/2}.mainHeader .menuItems a{font-size:2rem}.mainHeader .dropdown{opacity:0;grid-area:1/1/2/2;place-self:flex-start flex-end;transition:opacity .7s .1s}.mainHeader.isOpen .ico-burger{transition-delay:.12s;transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);transform:rotate(45deg)}.mainHeader.isOpen .ico-burger:after{top:0;transition:bottom 75ms,transform 75ms cubic-bezier(0.215, 0.61, 0.355, 1) .12s;transform:rotate(-90deg)}.mainHeader.isOpen .ico-burger:before{opacity:0}.mainHeader.isOpen .menuWrapper{clip-path:ellipse(200% 110% at 50% 0%);transition:clip-path .8s;visibility:visible}.mainHeader.isOpen .menuItems,.mainHeader.isOpen .dropdown{opacity:1;transition:opacity .5s .25s}}@keyframes color{0%,100%{fill:#1048f7}30%{fill:#1080f7}70%{fill:#143db9}}</style><script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/header.js.descarga" type="text/javascript"></script><style>.dropdown{position:relative;cursor:pointer;display:flex}#language-select{font-size:1.125rem}#language-select button,#language-select .asButton{text-transform:uppercase;font-weight:500;padding:7px 15px}#language-select .list{position:absolute;padding:16px;transform-origin:left top;top:calc(100% + 8px);right:0;animation-name:close_dropdown;animation-duration:.15s;border:1px solid rgba(var(--neutral_200))}#language-select .list li{transform:scale(0);transition:box-shadow .2s,background-color .2s;animation-name:close_dropdown_item;animation-duration:.4s;animation-timing-function:cubic-bezier(0.42, 0.83, 0.49, 1.35);animation-fill-mode:forwards}#language-select .list li+li{margin-top:6px;animation-delay:.15s}#language-select .list li a{width:100%}#language-select .list .abbrev:before{content:attr(data-abbrev)}#language-select .list.open{animation-name:open_dropdown}#language-select .list.open li{animation-name:open_dropdown_item}@keyframes open_dropdown{from{transform:scaleY(0)}to{transform:scaleY(1)}}@keyframes close_dropdown{from{transform:scaleY(1)}to{transform:scaleY(0)}}@keyframes open_dropdown_item{from{transform:scale(0)}to{transform:scale(1)}}@keyframes close_dropdown_item{from{transform:scale(1)}to{transform:scale(0)}}</style><script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/selectLanguage.js.descarga" type="text/javascript"></script><meta property="og:image" content="https://exfabrica.io/src/assets/imgs/illustrations/blog/emails-with-gmail-and-oauth2/illustration.webp"><meta property="og:title" content="How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica"><meta property="og:type" content="article"><meta property="article:published_time" content="2025-05-05T00:00:00.000Z"><meta property="article:author" content="Killian Le Vaillant"><title>How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica</title></head><body class="lang-en"><link href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/colors-light.css" type="text/css" rel="stylesheet"><svg class="uHidden" aria-hidden="true"><filter id="primary"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.06274509803921569 0 0 0 0 0 0.2823529411764706 0 0 0 0 0 0.9686274509803922 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="primary_dark"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.0784313725490196 0 0 0 0 0 0.01568627450980392 0 0 0 0 0 0.6784313725490196 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="secondary"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.0784313725490196 0 0 0 0 0 0.01568627450980392 0 0 0 0 0 0.6784313725490196 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="tertiary"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.8901960784313725 0 0 0 0 0 0.9019607843137255 0 0 0 0 0 0.984313725490196 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_0"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_100"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.9647058823529412 0 0 0 0 0 0.9647058823529412 0 0 0 0 0 0.984313725490196 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_200"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.8745098039215686 0 0 0 0 0 0.8745098039215686 0 0 0 0 0 0.9215686274509803 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_300"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.43137254901960786 0 0 0 0 0 0.45098039215686275 0 0 0 0 0 0.45098039215686275 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_400"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.09019607843137255 0 0 0 0 0 0.09019607843137255 0 0 0 0 0 0.09411764705882353 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="neutral_500"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_01"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.8823529411764706 0 0 0 0 0 0.8666666666666667 0 0 0 0 0 0.9882352941176471 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_dark_01"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.45098039215686275 0 0 0 0 0 0.38823529411764707 0 0 0 0 0 1 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_02"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.7529411764705882 0 0 0 0 0 0.9450980392156862 0 0 0 0 0 0.9568627450980393 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_dark_02"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0 0 0 0 0 0 0.8392156862745098 0 0 0 0 0 0.9568627450980393 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_03"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="0.984313725490196 0 0 0 0 0 0.9098039215686274 0 0 0 0 0 0.8823529411764706 0 0 0 0 0 1 0"></fecolormatrix></filter><filter id="decorative_dark_03"><fecolormatrix in="SourceGraphic" type="matrix" color-interpolation-filters="sRGB" values="1 0 0 0 0 0 0.5098039215686274 0 0 0 0 0 0.41568627450980394 0 0 0 0 0 1 0"></fecolormatrix></filter></svg><header class="mainHeader"><a class="skipLink" href="https://www.exfabrica.io/en/blog/how-to-securely-send-emails-via-gmail-using-oauth2-in-csharp-dotnet-a-step-by-step-guide.html#content">Skip to content</a><div class="mainWrapper"><div class="logo"><a href="https://www.exfabrica.io/en"><span class="uHidden">exFabrica - Back to the homepage</span></a></div><nav class="navigation"><button class="no-style toggle-btn" type="button" aria-expanded="false"><span class="uHidden">Open / close the menu</span><span class="ico-burger"></span></button><div class="menuWrapper"><ul class="menuItems"><li><a href="https://www.exfabrica.io/en/offer.html">Offers</a></li><li><a href="https://www.exfabrica.io/en/expertise.html">Expertise</a></li><li><a href="https://www.exfabrica.io/en/team.html">Team</a></li><li><a href="https://www.exfabrica.io/en/customers.html">Customers</a></li><li><a href="https://www.exfabrica.io/en/resources.html">Resources</a></li><li><a href="https://www.exfabrica.io/en/contact.html">Contact</a></li></ul><div class="dropdown" id="language-select"><button class="secondary" aria-label="Choose your language. Current language: English." aria-expanded="false" aria-controls="dropdownList"><span aria-hidden="true">en</span></button><ul class="list box" id="dropdownList" hidden=""><li><a class="list-item asButton secondary" href="https://www.exfabrica.io/blog/comment-securiser-l-envoi-d-emails-via-gmail-avec-oauth2-en-csharp-dotnet-le-guide-pas-a-pas.html"><span class="uHidden">Français</span><span class="abbrev" data-abbrev="FR" aria-hidden="true"></span></a></li><li><a class="list-item asButton secondary" href="https://www.exfabrica.io/en/blog/how-to-securely-send-emails-via-gmail-using-oauth2-in-csharp-dotnet-a-step-by-step-guide.html"><span class="uHidden">English</span><span class="abbrev" data-abbrev="EN" aria-hidden="true"></span></a></li></ul></div></div></nav></div></header><main id="content"><div class="mainWrapper"><header><a class="animated" href="https://www.exfabrica.io/en/resources.html#articles">← See all articles</a><span><img class="picture" src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/KLeVaillant.webp" alt="Killian Le Vaillant" loading="lazy"><small>Killian Le Vaillant - May 5, 2025</small></span><h1 class="styleH2">How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide</h1></header><section><h2 class="styleH3">Why has OAuth2 become indispensable?</h2>
|
|
<p>Since September 2024, Google has gradually begun removing support for so-called <a href="https://www.google.com/settings/security/lesssecureapps" target="_blank" rel="noreferer">Less Secure Apps</a>, which previously allowed sending email via SMTP using only a Gmail address and password. Although this method was simple to set up, it had security vulnerabilities and has therefore been disabled for new accounts.</p>
|
|
<p>If this option was enabled before September 2024, it is still possible (for now) to continue sending mail in this way. However, Google has not announced a final cutoff date, making this solution unstable and risky in the long term.</p>
|
|
<p>In this article, we will see how to create the OAuth 2.0 credentials required to send email via Gmail directly from the <a href="https://console.cloud.google.com/" target="_blank" rel="noreferer">Google Cloud Console</a>, and then how to integrate this authentication into a C# .NET application.</p>
|
|
<h3 class="styleH4">What Is OAuth2?</h3>
|
|
<p>OAuth 2.0 is a secure authorization protocol that allows an application to access protected resources (such as sending email via Gmail) on behalf of a user without needing to know their password. Instead of transmitting credentials directly, OAuth2 uses "tokens" to validate access. This mechanism is now widely used by major platforms (Google, Microsoft, Facebook, etc.) to provide better security while simplifying the user experience.</p></section><section><h2 class="styleH3">Creating OAuth2 credentials in the dans Google Cloud Console</h2>
|
|
<p>Before you can send emails via Gmail using OAuth2, you need to create credentials in the Google Cloud Console. Here is the step-by-step procedure:</p>
|
|
<h3 class="styleH4">1. Create a Google Cloud project</h3>
|
|
<p>Go to <a href="https://console.cloud.google.com/" target="_blank" rel="noreferer">https://console.cloud.google.com</a>.</p>
|
|
<p>Click on the project selector menu at the top of the page, then click "NEW PROJECT".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/select-a-project.webp" loading="lazy"><figcaption>
|
|
<p>"Select a project" button</p>
|
|
</figcaption>
|
|
</figure>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/new-project.webp" loading="lazy"><figcaption>
|
|
<p>"New project" button</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Give your project a name and click "Create". For this example, we'll name the project "Gmail OAuth tutorial". (Creation may take a few minutes)</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/create-project.webp" loading="lazy"><figcaption>
|
|
<p>Project creation page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Once the project is created, you can select it from the project list.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/select-project.webp" loading="lazy"><figcaption>
|
|
<p>Selecting the "Gmail OAuth tutorial" project</p>
|
|
</figcaption>
|
|
</figure>
|
|
<h3 class="styleH4">2. Configure the OAuth consent screen</h3>
|
|
<p>Before creating your credentials, you need to configure the OAuth consent screen. This tells Google which information will be shared with the user during authentication.</p>
|
|
<p>Go to the "APIs & Services" page, which you can access via the search bar.</p><p>
|
|
</p><figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/search-apis-services.webp" loading="lazy"><figcaption>
|
|
<p>Search for "APIs & Services"</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the left-hand menu, click "OAuth consent screen".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/menu-oauth-consent-screen.webp" loading="lazy"><figcaption>
|
|
<p>"OAuth consent screen" menu</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Click "GET STARTED" to begin setting up the OAuth consent screen.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-consent-screen-get-started.webp" loading="lazy"><figcaption>
|
|
<p>Get started screen</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Fill in the requested information in the "App Information" section, then click "NEXT":</p>
|
|
<ul>
|
|
<li>App name: The name of your application as it will appear to the user during authentication.</li>
|
|
<li>User support email: The support email address for your users.</li>
|
|
</ul>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-consent-screen-app-information.webp" loading="lazy"><figcaption>
|
|
<p>"App Information" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the "Audience" section, select "External".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-consent-screen-audience.webp" loading="lazy"><figcaption>
|
|
<p>"Audience" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>For the "Contact Information"section, you can keep the default email address or add another.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-consent-screen-contact-information.webp" loading="lazy"><figcaption>
|
|
<p>"Contact Information" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Finally, click "Continue", then "Create" to complete the OAuth consent screen setup.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-consent-screen-finish.webp" loading="lazy"><figcaption>
|
|
<p>"Finish" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<h3 class="styleH4">3. Publish the application to production</h3>
|
|
<p>Once the OAuth consent screen is configured, the application is in test mode. In this mode, refresh tokens expire after 7 days. This can be problematic for long-term use.</p>
|
|
<p>To avoid this limitation, we will publish the application to production. This notably allows obtaining refresh tokens that do not expire over time (as long as they are not manually revoked).</p>
|
|
<p>To publish your application:</p>
|
|
<p>We will now go to "Audience" and then click on "PUBLISH APP"</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/menu-audience-publish-app.webp" loading="lazy"><figcaption>
|
|
<p>"Audience" menu with the "publish app" button</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>A modal will appear; you can click on "CONFIRM" to publish the application.</p>
|
|
<p>⚠️ As you can see in the screenshot below, a warning message outlines the conditions that require manual verification before the application can go to production. Since this manual validation can take time, I recommend meeting the criteria to avoid this step, for example, by not setting a logo.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/publish-app-modal.webp" loading="lazy"><figcaption>
|
|
<p>Publication confirmation modal</p>
|
|
</figcaption>
|
|
</figure>
|
|
<h3 class="styleH4">4. Create OAuth 2.0 credentials</h3>
|
|
<p>Once the consent screen is configured and the application is published, you can create the OAuth 2.0 credentials.</p>
|
|
<p>Go back to the APIs & Services page and, in the left-hand menu, click on "Credentials".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/menu-credentials.webp" loading="lazy"><figcaption>
|
|
<p>"Credentials" menu</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>On the credentials page, click on "CREATE CREDENTIALS" and select the "OAuth client ID" option.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/create-credentials.webp" loading="lazy"><figcaption>
|
|
<p>"Create credentials" menu</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the "Application type" section, select "Web application", and you may enter a name if you wish.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-client-id.webp" loading="lazy"><figcaption>
|
|
<p>"OAuth client ID" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the "Authorized redirect URIs" section, add the following redirect URI: <a href="https://developers.google.com/oauthplayground" target="_blank" rel="noreferer">https://developers.google.com/oauthplayground</a>. This allows the application to redirect the user to Google's OAuth Playground tool, which will make it easier to generate the refresh token.</p>
|
|
<p>Once you've filled in all the information, click on "Create".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/authorized-redirect-uris.webp" loading="lazy"><figcaption>
|
|
<p>"Authorized redirect URIs" section</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>After the credentials are created, a window will appear displaying your <strong>Client ID</strong> and <strong>Client Secret</strong>. Make sure to note these details, as we will need them later.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-client-created.webp" loading="lazy"><figcaption>
|
|
<p>Client ID and Client Secret</p>
|
|
</figcaption>
|
|
</figure>
|
|
<h3 class="styleH4">5. Generate a Refresh Token</h3>
|
|
<p>As mentioned earlier, we'll use the <a href="https://developers.google.com/oauthplayground/" target="_blank" rel="noreferer">OAuth Playground</a> tool provided by Google to generate a <strong>refresh token</strong>. This tool allows you to simulate a full OAuth authentication flow without having to implement it in your own application.</p>
|
|
<p>Once the refresh token is generated, we'll be able to pass it directly to our C# .NET application. The app will then use this token to generate <strong>access tokens</strong> on the fly, without manual intervention or requiring the user to re-authenticate.</p>
|
|
<p>To do this, go to: <a href="https://developers.google.com/oauthplayground/" target="_blank" rel="noreferer">https://developers.google.com/oauthplayground/</a> and click on the gear icon in the top right corner of the page.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground.webp" loading="lazy"><figcaption>
|
|
<p>OAuth Playground home page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the "OAuth 2.0 Configuration" section, check the box "Use your own OAuth credentials" and enter your <strong>Client ID</strong> and <strong>Client Secret</strong> that you noted earlier. Then you can close the modal.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-credentials.webp" loading="lazy"><figcaption>
|
|
<p>OAuth Playground configuration modal</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>In the input field, enter <a href="https://mail.google.com/" target="_blank" rel="noreferer">https://mail.google.com</a> and click on "Authorize APIs".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-authorize-apis.webp" loading="lazy"><figcaption>
|
|
<p>API input field</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>A new window will open asking you to sign in to your Google account. Log in with the Gmail account you want to use to send emails.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-login.webp" loading="lazy"><figcaption>
|
|
<p>Google login page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Since the application hasn't been verified by Google yet, a warning message will appear. You can click on "Advanced settings" and then on "Go to...".</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-login-advanced-settings.webp" loading="lazy"><figcaption>
|
|
<p>Security warning page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>Once logged in, you'll see a page asking you to grant permissions to the application. Click "Continuer" to grant the required permissions.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-login-allow.webp" loading="lazy"><figcaption>
|
|
<p>Application permission page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>After granting permissions, you will be redirected back to the OAuth Playground. You will see a message confirming that the authorization was successful.</p>
|
|
<p>Now you can click on "Exchange authorization code for tokens" to obtain the <strong>refresh token</strong>.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-exchange-authorization-code.webp" loading="lazy"><figcaption>
|
|
<p>Authorization code exchange page</p>
|
|
</figcaption>
|
|
</figure>
|
|
<p>After clicking on "Exchange authorization code for tokens", a new section will appear showing the <strong>access token</strong> and the <strong>refresh token</strong>.</p>
|
|
<p>Be sure to note the <strong>refresh token</strong>, as we will need it for our C# .NET application.</p>
|
|
<figure><img src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/oauth-playground-refresh-token.webp" loading="lazy"><figcaption>
|
|
<p>Page showing the refresh token</p>
|
|
</figcaption>
|
|
</figure></section><section><h2 class="styleH3">Implementing email sending with OAuth2 in a C# .NET application</h2>
|
|
<p>We now have the necessary <strong>refresh token</strong> to send emails via Gmail. Let's now see how to use it in a C# .NET application.</p>
|
|
<h3 class="styleH4">1. Install the required packages</h3>
|
|
<p>To simplify the implementation of sending emails through Gmail using OAuth2, we will add two NuGet packages to our project:</p>
|
|
<ul>
|
|
<li>
|
|
<a href="https://www.nuget.org/packages/Google.Apis.Auth/" target="_blank" rel="noreferer"><strong>Google.Apis.Auth</strong></a>: This package allows us to securely generate access tokens from our refresh token in a way that is compliant with Google's OAuth2 standards.
|
|
</li>
|
|
<li>
|
|
<a href="https://www.nuget.org/packages/MailKit/" target="_blank" rel="noreferer"><strong>MailKit</strong></a>: A comprehensive library for sending emails. It significantly simplifies the setup and sending of messages via SMTP, especially when using OAuth2. MailKit also works well with standard SMTP authentication (username/password), but in our case, it will mainly allow us to send emails via Gmail using the previously obtained access token.
|
|
</li>
|
|
</ul>
|
|
<p>You can add these two packages to your project via the NuGet Package Manager Console:</p><pre><code>dotnet add package Google.Apis.Auth<br>dotnet add package MailKit</code></pre><p>If you're using Visual Studio, you can also add the packages via the graphical interface. Right-click on your project in the Solution Explorer, then select "Manage NuGet Packages". Search for the <strong>Google.Apis.Auth</strong> and <strong>MailKit</strong> packages, then click "Install".</p>
|
|
<h3 class="styleH4">2. Generate an Access Token from the Refresh Token</h3>
|
|
<p>Once the refresh token is obtained, you can generate an access token on the fly within your C# .NET application.</p>
|
|
<p>To do this, we'll create a dedicated method, for example named <code>GetGmailAccessToken</code>. This method is responsible for refreshing the access token only when necessary, based on the token's <code>IsStale</code> property, which indicates whether it is expired or about to expire.</p>
|
|
<p>To avoid generating a new token on every call, we store the token in a private static property of type <code>TokenResponse</code>. This allows us to reuse the same access token as long as it remains valid.</p><pre><code>private static TokenResponse? _gmailAccessToken;</code></pre><p>Here is an example implementation of this method (Replace <code>YOUR_CLIENT_ID</code>, <code>YOUR_CLIENT_SECRET</code>, and <code>YOUR_REFRESH_TOKEN</code> with your own credentials obtained from the Google Cloud Console and the OAuth Playground tool.):</p>
|
|
<figure class="githubCode">
|
|
<div aria-hidden="true">
|
|
<script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/58de0a439479e780801addea1e81bca0.js.descarga"></script><link rel="stylesheet" href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/gist-embed-59543e005c9c.css"><div id="gist137406035" class="gist">
|
|
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
|
|
<div class="gist-data">
|
|
<div class="js-gist-file-update-container js-task-list-container">
|
|
<div id="file-emailwriteservice-cs" class="file my-2">
|
|
|
|
<div itemprop="text" class="Box-body p-0 blob-wrapper data type-c " style="overflow: auto" tabindex="0" role="region" aria-label="EmailWriteService.cs content, created by killianlv on 07:52AM on April 14.">
|
|
|
|
|
|
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
|
|
|
|
<template class="js-file-alert-template"></template>
|
|
<template class="js-line-alert-template"></template>
|
|
|
|
<table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="EmailWriteService.cs">
|
|
<tbody><tr>
|
|
<td id="file-emailwriteservice-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
|
|
<td id="file-emailwriteservice-cs-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">private</span> <span class="pl-k">async</span> <span class="pl-smi">Task</span><span class="pl-c1"><</span><span class="pl-smi">string</span><span class="pl-c1">></span> <span class="pl-en">GetGmailAccessToken</span><span class="pl-kos">(</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
|
|
<td id="file-emailwriteservice-cs-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
|
|
<td id="file-emailwriteservice-cs-LC3" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">_gmailAccessToken</span> <span class="pl-c1">==</span> <span class="pl-c1">null</span> <span class="pl-c1">||</span> <span class="pl-s1">_gmailAccessToken</span><span class="pl-kos">.</span><span class="pl-s1">IsStale</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
|
|
<td id="file-emailwriteservice-cs-LC4" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
|
|
<td id="file-emailwriteservice-cs-LC5" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">var</span> <span class="pl-s1">clientSecrets</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">ClientSecrets</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
|
|
<td id="file-emailwriteservice-cs-LC6" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
|
|
<td id="file-emailwriteservice-cs-LC7" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">ClientId</span> <span class="pl-c1">=</span> <span class="pl-s1">YOUR_CLIENT_ID</span><span class="pl-kos">,</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
|
|
<td id="file-emailwriteservice-cs-LC8" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">ClientSecret</span> <span class="pl-c1">=</span> <span class="pl-s1">YOUR_CLIENT_SECRET</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
|
|
<td id="file-emailwriteservice-cs-LC9" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
|
|
<td id="file-emailwriteservice-cs-LC10" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
|
|
<td id="file-emailwriteservice-cs-LC11" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">var</span> <span class="pl-s1">credential</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">UserCredential</span><span class="pl-kos">(</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
|
|
<td id="file-emailwriteservice-cs-LC12" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">new</span> <span class="pl-smi">GoogleAuthorizationCodeFlow</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-s1">GoogleAuthorizationCodeFlow</span><span class="pl-kos">.</span><span class="pl-s1">Initializer</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
|
|
<td id="file-emailwriteservice-cs-LC13" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
|
|
<td id="file-emailwriteservice-cs-LC14" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">ClientSecrets</span> <span class="pl-c1">=</span> <span class="pl-s1">clientSecrets</span><span class="pl-kos">,</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
|
|
<td id="file-emailwriteservice-cs-LC15" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">Scopes</span> <span class="pl-c1">=</span> <span class="pl-k">new</span><span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-kos">{</span> <span class="pl-s">"https://mail.google.com/"</span> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
|
|
<td id="file-emailwriteservice-cs-LC16" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
|
|
<td id="file-emailwriteservice-cs-LC17" class="blob-code blob-code-inner js-file-line"> <span class="pl-s">"user"</span><span class="pl-kos">,</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
|
|
<td id="file-emailwriteservice-cs-LC18" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">new</span> <span class="pl-smi">TokenResponse</span> <span class="pl-kos">{</span> <span class="pl-s1">RefreshToken</span> <span class="pl-c1">=</span> <span class="pl-s1">YOUR_REFRESH_TOKEN</span> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
|
|
<td id="file-emailwriteservice-cs-LC19" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
|
|
<td id="file-emailwriteservice-cs-LC20" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
|
|
<td id="file-emailwriteservice-cs-LC21" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">credential</span><span class="pl-kos">.</span><span class="pl-en">RefreshTokenAsync</span><span class="pl-kos">(</span><span class="pl-s1">CancellationToken</span><span class="pl-kos">.</span><span class="pl-s1">None</span><span class="pl-kos">)</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
|
|
<td id="file-emailwriteservice-cs-LC22" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
|
|
<td id="file-emailwriteservice-cs-LC23" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">_gmailAccessToken</span> <span class="pl-c1">=</span> <span class="pl-s1">credential</span><span class="pl-kos">.</span><span class="pl-s1">Token</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
|
|
<td id="file-emailwriteservice-cs-LC24" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
|
|
<td id="file-emailwriteservice-cs-LC25" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">else</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
|
|
<td id="file-emailwriteservice-cs-LC26" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
|
|
<td id="file-emailwriteservice-cs-LC27" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Exception</span><span class="pl-kos">(</span><span class="pl-s">"Failed to refresh the OAuth2 token."</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
|
|
<td id="file-emailwriteservice-cs-LC28" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
|
|
<td id="file-emailwriteservice-cs-LC29" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
|
|
<td id="file-emailwriteservice-cs-LC30" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
|
|
<td id="file-emailwriteservice-cs-LC31" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-s1">_gmailAccessToken</span><span class="pl-kos">.</span><span class="pl-s1">AccessToken</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
|
|
<td id="file-emailwriteservice-cs-LC32" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">}</span></td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="gist-meta">
|
|
<a href="https://gist.github.com/killianlv/58de0a439479e780801addea1e81bca0/raw/4692d38664b2a3d9e82d0dd6ea7365f56a477f12/EmailWriteService.cs" style="float:right" class="Link--inTextBlock">view raw</a>
|
|
<a href="https://gist.github.com/killianlv/58de0a439479e780801addea1e81bca0#file-emailwriteservice-cs" class="Link--inTextBlock">
|
|
EmailWriteService.cs
|
|
</a>
|
|
hosted with ❤ by <a class="Link--inTextBlock" href="https://github.com/">GitHub</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<figcaption class="uHidden">Github code</figcaption>
|
|
</figure>
|
|
<p>Thanks to this method, you can easily retrieve a valid access token before each email is sent, without requiring the user to authenticate again. This is the function you'll call before using MailKit to send your emails.</p>
|
|
<h3 class="styleH4">3. Send an email with MailKit</h3>
|
|
<p>Once the <strong>access token</strong> is generated using the <strong>refresh token</strong>, it's time to send an email through Gmail using the SMTP protocol and OAuth2 authentication.</p>
|
|
<p>To do this, we'll create a method that takes as a parameter an <code>EmailRequestBo</code> object containing the required information: sender, one or more recipients, subject, and HTML body of the message.</p>
|
|
<p>Here's the structure of the <code>EmailRequestBo</code> object we'll use in our example:</p>
|
|
<figure class="githubCode">
|
|
<div aria-hidden="true">
|
|
<script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/630ee9e02a2f32f28e866c49e44eaf56.js.descarga"></script><link rel="stylesheet" href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/gist-embed-59543e005c9c.css"><div id="gist137407025" class="gist">
|
|
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
|
|
<div class="gist-data">
|
|
<div class="js-gist-file-update-container js-task-list-container">
|
|
<div id="file-emailrequestbo-cs" class="file my-2">
|
|
|
|
<div itemprop="text" class="Box-body p-0 blob-wrapper data type-c " style="overflow: auto" tabindex="0" role="region" aria-label="EmailRequestBo.cs content, created by killianlv on 08:41AM on April 14.">
|
|
|
|
|
|
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
|
|
|
|
<template class="js-file-alert-template"></template>
|
|
<template class="js-line-alert-template"></template>
|
|
|
|
<table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="EmailRequestBo.cs">
|
|
<tbody><tr>
|
|
<td id="file-emailrequestbo-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
|
|
<td id="file-emailrequestbo-cs-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">EmailRequestBo</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
|
|
<td id="file-emailrequestbo-cs-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
|
|
<td id="file-emailrequestbo-cs-LC3" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">string</span> <span class="pl-s1">Subject</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">string</span><span class="pl-kos">.</span><span class="pl-s1">Empty</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
|
|
<td id="file-emailrequestbo-cs-LC4" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">string</span> <span class="pl-s1">SenderName</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">string</span><span class="pl-kos">.</span><span class="pl-s1">Empty</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
|
|
<td id="file-emailrequestbo-cs-LC5" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">IEnumerable</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span> <span class="pl-s1">To</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">List</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
|
|
<td id="file-emailrequestbo-cs-LC6" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">IEnumerable</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span> <span class="pl-s1">Cc</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">List</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
|
|
<td id="file-emailrequestbo-cs-LC7" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">IEnumerable</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span> <span class="pl-s1">Bcc</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">List</span><span class="pl-c1"><</span><span class="pl-smi">EmailContactBo</span><span class="pl-c1">></span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
|
|
<td id="file-emailrequestbo-cs-LC8" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">string</span> <span class="pl-s1">HtmlContent</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">string</span><span class="pl-kos">.</span><span class="pl-s1">Empty</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailrequestbo-cs-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
|
|
<td id="file-emailrequestbo-cs-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">}</span></td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="gist-meta">
|
|
<a href="https://gist.github.com/killianlv/630ee9e02a2f32f28e866c49e44eaf56/raw/dfb39973d57f3a452e9535d80d4f5bbebd4b32ca/EmailRequestBo.cs" style="float:right" class="Link--inTextBlock">view raw</a>
|
|
<a href="https://gist.github.com/killianlv/630ee9e02a2f32f28e866c49e44eaf56#file-emailrequestbo-cs" class="Link--inTextBlock">
|
|
EmailRequestBo.cs
|
|
</a>
|
|
hosted with ❤ by <a class="Link--inTextBlock" href="https://github.com/">GitHub</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<figcaption class="uHidden">Github code</figcaption>
|
|
</figure>
|
|
<p>And for each contact (main recipient, CC, or BCC), we use the following class:</p>
|
|
<figure class="githubCode">
|
|
<div aria-hidden="true">
|
|
<script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/1c936be954955b8014094415c0fafe9d.js.descarga"></script><link rel="stylesheet" href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/gist-embed-59543e005c9c.css"><div id="gist137407040" class="gist">
|
|
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
|
|
<div class="gist-data">
|
|
<div class="js-gist-file-update-container js-task-list-container">
|
|
<div id="file-emailcontactbo-cs" class="file my-2">
|
|
|
|
<div itemprop="text" class="Box-body p-0 blob-wrapper data type-c " style="overflow: auto" tabindex="0" role="region" aria-label="EmailContactBo.cs content, created by killianlv on 08:42AM on April 14.">
|
|
|
|
|
|
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
|
|
|
|
<template class="js-file-alert-template"></template>
|
|
<template class="js-line-alert-template"></template>
|
|
|
|
<table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="EmailContactBo.cs">
|
|
<tbody><tr>
|
|
<td id="file-emailcontactbo-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
|
|
<td id="file-emailcontactbo-cs-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">EmailContactBo</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailcontactbo-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
|
|
<td id="file-emailcontactbo-cs-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailcontactbo-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
|
|
<td id="file-emailcontactbo-cs-LC3" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">string</span> <span class="pl-s1">Email</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">string</span><span class="pl-kos">.</span><span class="pl-s1">Empty</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailcontactbo-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
|
|
<td id="file-emailcontactbo-cs-LC4" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">string</span> <span class="pl-s1">Name</span> <span class="pl-kos">{</span> <span class="pl-k">get</span><span class="pl-kos">;</span> <span class="pl-k">set</span><span class="pl-kos">;</span> <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-smi">string</span><span class="pl-kos">.</span><span class="pl-s1">Empty</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailcontactbo-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
|
|
<td id="file-emailcontactbo-cs-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">}</span></td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="gist-meta">
|
|
<a href="https://gist.github.com/killianlv/1c936be954955b8014094415c0fafe9d/raw/15fe410a8d5d94367f3b200d7df6bfaaf74800e9/EmailContactBo.cs" style="float:right" class="Link--inTextBlock">view raw</a>
|
|
<a href="https://gist.github.com/killianlv/1c936be954955b8014094415c0fafe9d#file-emailcontactbo-cs" class="Link--inTextBlock">
|
|
EmailContactBo.cs
|
|
</a>
|
|
hosted with ❤ by <a class="Link--inTextBlock" href="https://github.com/">GitHub</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<figcaption class="uHidden">Github code</figcaption>
|
|
</figure>
|
|
<p>Now here is a complete example of a <code>SendEmail</code> method that sends an HTML email using Gmail and OAuth2:</p>
|
|
<figure class="githubCode">
|
|
<div aria-hidden="true">
|
|
<script src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/0fd15ed60c8903d575984a55e1a28a36.js.descarga"></script><link rel="stylesheet" href="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/gist-embed-59543e005c9c.css"><div id="gist137407136" class="gist">
|
|
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
|
|
<div class="gist-data">
|
|
<div class="js-gist-file-update-container js-task-list-container">
|
|
<div id="file-emailwriteservice-cs" class="file my-2">
|
|
|
|
<div itemprop="text" class="Box-body p-0 blob-wrapper data type-c " style="overflow: auto" tabindex="0" role="region" aria-label="EmailWriteService.cs content, created by killianlv on 08:49AM on April 14.">
|
|
|
|
|
|
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
|
|
|
|
<template class="js-file-alert-template"></template>
|
|
<template class="js-line-alert-template"></template>
|
|
|
|
<table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="EmailWriteService.cs">
|
|
<tbody><tr>
|
|
<td id="file-emailwriteservice-cs-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
|
|
<td id="file-emailwriteservice-cs-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">async</span> <span class="pl-smi">Task</span> <span class="pl-en">SendEmail</span><span class="pl-kos">(</span><span class="pl-smi">EmailRequestBo</span> <span class="pl-s1">request</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
|
|
<td id="file-emailwriteservice-cs-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
|
|
<td id="file-emailwriteservice-cs-LC3" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">// Retrieve the OAuth2 token</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
|
|
<td id="file-emailwriteservice-cs-LC4" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">var</span> <span class="pl-s1">accessToken</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">GetGmailAccessToken</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
|
|
<td id="file-emailwriteservice-cs-LC5" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
|
|
<td id="file-emailwriteservice-cs-LC6" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">// Create the email message</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
|
|
<td id="file-emailwriteservice-cs-LC7" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">var</span> <span class="pl-s1">message</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">MimeMessage</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
|
|
<td id="file-emailwriteservice-cs-LC8" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">From</span><span class="pl-kos">.</span><span class="pl-en">Add</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">MailboxAddress</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">SenderName</span><span class="pl-kos">,</span> <span class="pl-s1">YOUR_SENDER_EMAIL</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
|
|
<td id="file-emailwriteservice-cs-LC9" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
|
|
<td id="file-emailwriteservice-cs-LC10" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">foreach</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">to</span> <span class="pl-k">in</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">To</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
|
|
<td id="file-emailwriteservice-cs-LC11" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">To</span><span class="pl-kos">.</span><span class="pl-en">Add</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">MailboxAddress</span><span class="pl-kos">(</span><span class="pl-s1">to</span><span class="pl-kos">.</span><span class="pl-s1">Name</span><span class="pl-kos">,</span> <span class="pl-s1">to</span><span class="pl-kos">.</span><span class="pl-s1">Email</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
|
|
<td id="file-emailwriteservice-cs-LC12" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
|
|
<td id="file-emailwriteservice-cs-LC13" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">foreach</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">cc</span> <span class="pl-k">in</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">Cc</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
|
|
<td id="file-emailwriteservice-cs-LC14" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">Cc</span><span class="pl-kos">.</span><span class="pl-en">Add</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">MailboxAddress</span><span class="pl-kos">(</span><span class="pl-s1">cc</span><span class="pl-kos">.</span><span class="pl-s1">Name</span><span class="pl-kos">,</span> <span class="pl-s1">cc</span><span class="pl-kos">.</span><span class="pl-s1">Email</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
|
|
<td id="file-emailwriteservice-cs-LC15" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
|
|
<td id="file-emailwriteservice-cs-LC16" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">foreach</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">bcc</span> <span class="pl-k">in</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">Bcc</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
|
|
<td id="file-emailwriteservice-cs-LC17" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">Bcc</span><span class="pl-kos">.</span><span class="pl-en">Add</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">MailboxAddress</span><span class="pl-kos">(</span><span class="pl-s1">bcc</span><span class="pl-kos">.</span><span class="pl-s1">Name</span><span class="pl-kos">,</span> <span class="pl-s1">bcc</span><span class="pl-kos">.</span><span class="pl-s1">Email</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
|
|
<td id="file-emailwriteservice-cs-LC18" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
|
|
<td id="file-emailwriteservice-cs-LC19" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">Subject</span> <span class="pl-c1">=</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">Subject</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
|
|
<td id="file-emailwriteservice-cs-LC20" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">message</span><span class="pl-kos">.</span><span class="pl-s1">Body</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">TextPart</span><span class="pl-kos">(</span><span class="pl-s">"html"</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-s1">Text</span> <span class="pl-c1">=</span> <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-s1">HtmlContent</span> <span class="pl-kos">}</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
|
|
<td id="file-emailwriteservice-cs-LC21" class="blob-code blob-code-inner js-file-line"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
|
|
<td id="file-emailwriteservice-cs-LC22" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">// Send using MailKit</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
|
|
<td id="file-emailwriteservice-cs-LC23" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">using</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">SmtpClient</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
|
|
<td id="file-emailwriteservice-cs-LC24" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">{</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
|
|
<td id="file-emailwriteservice-cs-LC25" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">Connect</span><span class="pl-kos">(</span><span class="pl-s">"smtp.gmail.com"</span><span class="pl-kos">,</span> <span class="pl-c1">587</span><span class="pl-kos">,</span> <span class="pl-s1">SecureSocketOptions</span><span class="pl-kos">.</span><span class="pl-s1">StartTls</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
|
|
<td id="file-emailwriteservice-cs-LC26" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">Authenticate</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">SaslMechanismOAuth2</span><span class="pl-kos">(</span><span class="pl-s1">YOUR_SENDER_EMAIL</span><span class="pl-kos">,</span> <span class="pl-s1">accessToken</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
|
|
<td id="file-emailwriteservice-cs-LC27" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">await</span> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">SendAsync</span><span class="pl-kos">(</span><span class="pl-s1">message</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
|
|
<td id="file-emailwriteservice-cs-LC28" class="blob-code blob-code-inner js-file-line"> <span class="pl-s1">client</span><span class="pl-kos">.</span><span class="pl-en">Disconnect</span><span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
|
|
<td id="file-emailwriteservice-cs-LC29" class="blob-code blob-code-inner js-file-line"> <span class="pl-kos">}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td id="file-emailwriteservice-cs-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
|
|
<td id="file-emailwriteservice-cs-LC30" class="blob-code blob-code-inner js-file-line"><span class="pl-kos">}</span></td>
|
|
</tr>
|
|
</tbody></table>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="gist-meta">
|
|
<a href="https://gist.github.com/killianlv/0fd15ed60c8903d575984a55e1a28a36/raw/719220f3ee036725bd17f7a43b78e21f6de8bd0f/EmailWriteService.cs" style="float:right" class="Link--inTextBlock">view raw</a>
|
|
<a href="https://gist.github.com/killianlv/0fd15ed60c8903d575984a55e1a28a36#file-emailwriteservice-cs" class="Link--inTextBlock">
|
|
EmailWriteService.cs
|
|
</a>
|
|
hosted with ❤ by <a class="Link--inTextBlock" href="https://github.com/">GitHub</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<figcaption class="uHidden">Github code</figcaption>
|
|
</figure>
|
|
<p>Replace <code>YOUR_SENDER_EMAIL</code> with the address of the account you used to generate the <strong>refresh token</strong> in the <a href="https://developers.google.com/oauthplayground/" target="_blank" rel="noreferrer">OAuth Playground</a>. This is the account that granted access via the Gmail API and will be used to send the emails.</p>
|
|
<p>This method uses the <strong>MailKit</strong> library to handle the email sending. It establishes a secure connection to Gmail's SMTP server (via STARTTLS), then uses the OAuth2 authentication mechanism with the previously generated access token.</p><with>this approach, you can securely send emails through Gmail without storing any plaintext passwords, while staying aligned with Google's current security recommendations.<p></p></with></section><section><h2 class="styleH3">Conclusion</h2>
|
|
<p>Securing email sending via Gmail is now essential, and OAuth2 stands out as the modern and reliable solution to achieve this. In this guide, we covered how to:</p>
|
|
<ul>
|
|
<li><strong>Create OAuth2 credentials</strong> in the Google Cloud Console and configure the consent screen.</li>
|
|
<li><strong>Publish the application to production</strong> in order to obtain long-lived refresh tokens (and avoid their expiration after 7 days).</li>
|
|
<li><strong>Use the OAuth Playground</strong> to easily generate a refresh token.</li>
|
|
<li><strong>Implement email sending with OAuth2</strong> in a C# .NET application using the Google.Apis.Auth and MailKit packages.</li>
|
|
</ul></section><div class="navigation"></div></div></main><footer><div class="mainWrapper"><div class="carbonbadge" id="wcb"><style>#wcb.carbonbadge{--b1:#0e11a8;--b2:#00ffbc;font-size:15px;text-align:center;color:var(--b1);line-height:1.15}#wcb.carbonbadge sub{vertical-align:middle;position:relative;top:.3em;font-size:.7em}#wcb #wcb_2,#wcb #wcb_a,#wcb #wcb_g{display:inline-flex;justify-content:center;align-items:center;text-align:center;font-size:1em;line-height:1.15;font-family:-apple-system,BlinkMacSystemFont,sans-serif;text-decoration:none;margin:.2em 0}#wcb #wcb_a,#wcb #wcb_g{padding:.3em .5em;border:.13em solid var(--b2)}#wcb #wcb_g{border-radius:.3em 0 0 .3em;background:#fff;border-right:0;min-width:8.2em}#wcb #wcb_a{border-radius:0 .3em .3em 0;border-left:0;background:var(--b1);color:#fff;font-weight:700;border-color:var(--b1)}#wcb.wcb-d #wcb_a{color:var(--b1);background:var(--b2);border-color:var(--b2)}#wcb.wcb-d #wcb_2{color:#fff}</style><div id="wcb_p"><span id="wcb_g">0.03g of CO<sub>2</sub>/view</span><a id="wcb_a" target="_blank" rel="noopener" href="https://websitecarbon.com/">Website Carbon</a></div><span id="wcb_2"> Cleaner than 97% of pages tested</span></div><a href="https://www.exfabrica.io/en/legalNotices.html">Legal notices</a><small>© exFabrica 2025</small></div></footer><script type="text/javascript" src="./How to securely send emails via Gmail using OAuth2 in C# .NET - a step-by-step guide - exFabrica_files/b.min.js.descarga" defer=""></script></body></html> |