Mail.dll – Add MandroidI18n in Xamarin release mode

Mail.dll requires multiple encodings to work.

By default in the Release mode, Xamarin applications link only most common encodings. Of course this is not enough to handle multi-national email messages.

If on startup your application receives MissingEncodingException error, you need to add MandroidI18n into your .csproj (e.g. App1.Android.csproj):

<MandroidI18n>All</MandroidI18n>

You might need to unload the project first to be able to edit it:

Alternatively you can go to:

Android project -> Properties -> Android Options

and select all possible encodings in:

Linker properties -> Additional supported encodings

Order process maintenance scheduled for Feb 24, 2021

We will be conducting planned maintenance to ordering system on Wednesday, February 24, 2021

During the planned maintenance, the system will continue to take orders. However customers may see temporary delays in fulfillment and order confirmation emails.

Once the maintenance is finished, we expect all functionality to resume; orders will be processed, and order confirmation emails will be sent to customers.

Access shared/delegate mailbox of Office 365

Enable IMAP/POP3

First make sure IMAP / POP3 are turned on properly: Enable IMAP / POP3 in Office 365

Shared mailbox permissions

Make sure you have access to the shared mailbox. Log in to Microsoft 365 admin portal at https://admin.microsoft.com/ as an administrator, go to Users/Active users tab and select shared mailbox:

On the Mail tab, in Mailbox permissions click Read and manage permissions:

Make sure your user is on the list:

Enable IMAP/POP3 for shared mailbox

On the same screen go to Manage email apps:

and select IMAP and POP3:

Now, there are 2 ways of accessing a shared mailbox in Office 365:

Using regular IMAP basic authentication and a using OAuth 2.0.

Shared mailbox – basic authentication [deprecated]

It is no longer possible to re-enable Basic Auth or use App passwords.

You’ll need to use OAuth described below.

To use basic authentication you’ll need to  re-enable Basic Auth for your tenant:
https://www.limilabs.com/blog/office-365-prevent-basic-auth-disabled

Make sure IMAP/POP3 access is configured and basic authentication is turned on:
Enable IMAP / POP3 in Office 365

Consider using Application passwords for your account instead of your primary password:
Application passwords in Office 365

Try authenticating to users’ regular mailbox with his credentials (or App password) to check if basic authentication works and the user/password is correct:

client.UseBestLogin("AlexW@example.com", "AlexWPass-or-AlexWAppPass");

Access the shared mailbox

Use the following user format:

Username@DomainName\Shared@DomainName

You must use Login method:

client.Login(@"AlexW@example.com\invoices@example.com", "AlexWPass-or-AlexWAppPass"); 

-or-

alternatively you may use LoginPlain method:

client.LoginPlain("invoices@example.com", "AlexW@example.com", "AlexWPass-or-AlexWAppPass");

Don’t use UseBestLogin for Office365 shared mailboxes and basic authentication.

The reason is Office  365 advertises LOGIN PLAIN as a preferred login method and UseBestLogin chooses to use it. However Office 365 does not recognize Username@DomainName\Shared@DomainName user pattern when using LOGIN PLAIN. For Office 365 to accept a LOGIN PLAIN to a shared mailbox, you need to provide all 3 parameters separately: shared mailbox, user and user password – use LoginPlain to do that.

Shared mailbox – OAuth 2.0

It is much simpler with OAuth. Use any of the available OAuth 2.0 flows:

Daemons/Services: Password grant (MFA/2FA must be turned off for this account):
https://www.limilabs.com/blog/oauth2-password-grant-office365-exchange-imap-pop3-smtp

Daemons/Services: Client credential flow:
https://www.limilabs.com/blog/oauth2-client-credential-flow-office365-exchange-imap-pop3-smtp

Web apps (requires user interaction):
https://www.limilabs.com/blog/oauth2-web-flow-office365-exchange-imap-pop3-smtp

Standalone devices (requires very little interaction):
https://www.limilabs.com/blog/oauth2-device-flow-office365-exchange-imap-pop3-smtp

Desktop apps (requires user interaction):
https://www.limilabs.com/blog/oauth2-office365-exchange-imap-pop3-smtp

When you’ve obtained an access token you simply use it to access shared mailbox:

string accessToken = result.AccessToken;

using (Imap client = new Imap())
{
    client.ConnectSSL("outlook.office365.com");
    client.LoginOAUTH2("invoices@example.com", accessToken);

    client.SelectInbox();

    List<long> uids = imap.Search(Flag.Unseen);
    foreach (long uid in uids)
    {
        var eml = imap.GetMessageByUID(uid)
        IMail email = new MailBuilder().CreateFromEml();
        string subject = email.Subject);
    }
    client.Close();
}

Office365: Temporary server error. Please try again later. PRX4

When using Mail.dll SMTP .NET client to connect to Office365 using OAUTH 2.0 you may receive a following error during authentication phase:

Temporary server error. Please try again later. PRX4

SMTP log looks more or less like this:

Connecting to ‘outlook.office365.com:587’, SSL/TLS: False.

S: 220 AS8PR04CA0136.outlook.office365.com Microsoft ESMTP MAIL Service ready at Thu, 28 Jan 2021 15:43:35 + 0000
C: EHLO[IPv6:2a02:]
S: 250-AS8PR04CA0136.outlook.office365.com Hello[2a02:]
S: 250-SIZE 157286400
S: 250-PIPELINING
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250-STARTTLS
S: 250-8BITMIME
S: 250-BINARYMIME
S: 250-CHUNKING
S: 250 SMTPUTF8
C: STARTTLS
S: 220 2.0.0 SMTP server ready
C: EHLO[IPv6:2a02:]
S: 250-AS8PR04CA0136.outlook.office365.com Hello [2a02:]
S: 250-SIZE 157286400
S: 250-PIPELINING
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250-AUTH LOGIN XOAUTH2
S: 250-8BITMIME
S: 250-BINARYMIME
S: 250-CHUNKING
S: 250 SMTPUTF8
C: AUTH XOAUTH2 dXNlcj1B...EEBAQ==
S: 451 4.7.0 Temporary server error. Please try again later. PRX4[AS8PR04CA0136.eurprd04.prod.outlook.com]

It is a bug on the Office365 side when new business account is created with Microsoft. 

Although SMTP is enabled by default, it is not working. The workaround for this issue is to turn Authenticated SMTP off and turn it on again.

After creating the e-mail account, you have to edit the account.

Go to https://admin.microsoft.com/ and click Setup.

On the “Active users” list find the account you are using:

Then go to “Mail” tab then click “Manage email apps

There is an option called “Authenticated SMTP”.  It is ticked by default, however to actually make it work you have to uncheck it and save the changes, then go back in and check it again it and save the changes.

You may need to leave it unchecked for some time and wait for some time when it is rechecked, before it starts working.

After this change Mail.dll client can authenticate successfully using OAuth 2.0:

C: AUTH XOAUTH2 dXNlcj1B...BAQ==
S: 235 2.7.0 Authentication successful
C: QUIT

OAuth 2.0 password grant with Office365/Exchange IMAP/POP3/SMTP

This article shows how to implement OAuth 2.0 password grant flow to access Office365 via IMAP, POP3 or SMTP using Mail.dll .NET email client.

Enable email protocols

Make sure IMAP/POP3/SMTP is enabled for your organization and mailbox:
Enable IMAP/POP3/SMTP in Office 365

Disable MFA for account

Password grant flow requires Multi-Factor Authentication (MFA) to be disabled for this mailbox – make also sure there are no Active Directory policies that match this account and require MFA (you can of course have policies that match all other accounts).

Go to Microsoft365 admin center. Select Setup on the left menu and in the Sign-in and security section select Configure multifactor authentication (MFA):

You can use per-user MFA or AD policies.

Register and configure application

Register your application in Azure Portal, here’s a detailed guide how to do that:
https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app

Enable additional flows:

Then you need to apply correct API permissions and grant the admin consent for your domain.

In the API permissions / Add a permission wizard, select Microsoft Graph and then Delegated permissions to find the following permission scopes listed:

  • offline_access
  • email
  • IMAP.AccessAsUser.All
  • POP.AccessAsUser.All
  • SMTP.Send

Remember to Grant admin consent:

Obtain OAuth 2.0 token

Use Microsoft Authentication Library for .NET (MSAL.NET) nuget package to obtain an access token:
https://www.nuget.org/packages/Microsoft.Identity.Client/

string clientId = "Application (client) ID";
string tenantId = "Directory (tenant) ID";

string userEmail = "Username for mailbox";
string userPassword = "Password for that user";

IPublicClientApplication app = PublicClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .Build();

var scopes = new string[] 
{
    "offline_access",
    "email",
    "https://outlook.office.com/IMAP.AccessAsUser.All",
    "https://outlook.office.com/POP.AccessAsUser.All",
    "https://outlook.office.com/SMTP.Send",
};

Now acquire an access token and a user name:

string userName;
string accessToken;

var account = (await app.GetAccountsAsync()).FirstOrDefault();

try
{
    AuthenticationResult refresh = await app
        .AcquireTokenSilent(scopes, account)
        .ExecuteAsync();

    userName = refresh.Account.Username;
    accessToken = refresh.AccessToken;
}
catch (MsalUiRequiredException e)
{
    SecureString securePassword = new SecureString();
    foreach (char c in userPassword)
    {
        securePassword.AppendChar(c);
    }

    var result = await app.AcquireTokenByUsernamePassword(
        scopes, 
        userEmail, 
        securePassword).ExecuteAsync();

    userName = result.Account.Username;
    accessToken = result.AccessToken;
}

Install Mail.dll email library

The easiest way to install Mail.dll is to download it from nuget via Package Manager:

PM> Install-Package Mail.dll

Alternatively you can download Mail.dll directly from our website.

Download and process emails

Finally you can connect using IMAP/POP3/SMTP, authenticate and download user’s emails:

using (Imap client = new Imap())
{
    client.ConnectSSL("outlook.office365.com");
    client.LoginOAUTH2(userName, accessToken);
 
    client.SelectInbox();

    List<long> uids = imap.Search(Flag.Unseen);
    foreach (long uid in uids)
    {
        IMail email = new MailBuilder()
                .CreateFromEml(imap.GetMessageByUID(uid));
        string subject = email.Subject;
   }

    client.Close();
} 


Get Mail.dll