Blog | Limilabs https://www.limilabs.com/blog Tue, 12 Dec 2023 08:35:17 +0000 en-US hourly 1 https://wordpress.org/?v=6.3.4 IMAP component for .NET https://www.limilabs.com/blog/imap-component-for-net Wed, 29 Nov 2023 11:51:36 +0000 http://www.limilabs.com/blog/?p=219 Mail.dll email component includes an excellent IMAP email component. Unleash the full potential of email management with Mail.dll’s outstanding IMAP email component. It offers .NET developers an unparalleled tool for handling IMAP email protocol. From retrieving messages to managing folders and attachments, the IMAP component in Mail.dll simplifies complex tasks into user-friendly functions. Mail.dll is […]

The post IMAP component for .NET first appeared on Blog | Limilabs.

]]>
Mail.dll email component includes an excellent IMAP email component. Unleash the full potential of email management with Mail.dll’s outstanding IMAP email component.

It offers .NET developers an unparalleled tool for handling IMAP email protocol. From retrieving messages to managing folders and attachments, the IMAP component in Mail.dll simplifies complex tasks into user-friendly functions.

Mail.dll is available for all regular .NET framework versions as well as for most recent .net 6 and .net 7.

IMAP, short for Internet Message Access Protocol, is one of the two most prevalent Internet standard protocols for e-mail retrieval, the other being Post Office Protocol – POP3 (also available in Mail.dll).

IMAP has many advantages over POP3, most important are using folders to group emails, saving seen/unseen state of the messages and search capability.

This article is going to show how easy is to connect to use IMAP client from .NET, download and parse unseen messages.

Installation

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.

Connect to IMAP

First you need connect to IMAP server. You should use Imap class for that. Using block ensures that IMAP connection is properly closed and disposed when you’re done.

using(Imap imap = new Imap())

In most cases you should be using TLS secured connection – ConnectSSL method will choose a correct port and perform SSL/TLS negotiation, then you perform IMAP authentictation:

	imap.ConnectSSL("imap.server.com");
	imap.UseBestLogin("user", "password");

Mail.dll supports OAuth 2.0 for authentication, you can find OAuth2 samples for Office365 and Gmail on the Mail.dll samples page.

For Gmail you may want to use Gmail’s App Passwords.

Search for unseen emails

As IMAP groups messages into folder you need to select a well know INBOX folder. All new, received emails are first placed in the INBOX folder first:

imap.SelectInbox();

Then you perform a search that find all unseen messages

List<long> uids = imap.Search(Flag.Unseen);

Download and parse emails

Finally you download emails one-by-one and parse them. You should use MailBuider class to parse emails:

var eml = imap.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(eml);

Entire code to download emails in .net

Entire code to download emails using IMAP is less than 20 lines:

using(Imap imap = new Imap())
{
	imap.ConnectSSL("imap.server.com");	// or Connect for no TLS
	imap.UseBestLogin("user", "password");

	imap.SelectInbox();
	List<long> uids = imap.Search(Flag.Unseen);

	foreach (long uid in uids)
	{
		var eml = imap.GetMessageByUID(uid);
		IMail email = new MailBuilder().CreateFromEml(eml);

		string subject = mail.Subject;
	}
	imap.Close();
}

and for those who like VB.NET more:

Using imap As New Imap()
	imap.ConnectSSL("imap.server.com")
	imap.UseBestLogin("user", "password")

	imap.SelectInbox()
	Dim uids As List(Of Long) = imap.Search(Flag.Unseen)

	For Each uid As Long In uids
		Dim mail As IMail = New MailBuilder()_
			.CreateFromEml(imap.GetMessageByUID(uid))

		Console.WriteLine(mail.Subject)
	Next
	imap.Close()
End Using

It can’t get much simpler than that!

Summary

You can use Mail.dll .NET IMAP component to:

It works perfectly with Exchange, Office365, Gmail and all other IMAP servers.

Just give Mail.dll a try and download it at: Mail.dll .NET IMAP component


Get Mail.dll

The post IMAP component for .NET first appeared on Blog | Limilabs.

]]>
How to search IMAP in .NET https://www.limilabs.com/blog/how-to-search-imap-in-net https://www.limilabs.com/blog/how-to-search-imap-in-net#comments Mon, 31 Jul 2023 13:49:47 +0000 http://www.limilabs.com/blog/?p=181 One of many advantages IMAP protocol has over POP3 protocol is the ability to search. There are several ways of performing search using Mail.dll .NET IMAP library: IMAP search is done entirely on the server side, which means that it’s fast and doesn’t require Mail.dll client to download much data over the network. Installation The […]

The post How to search IMAP in .NET first appeared on Blog | Limilabs.

]]>
One of many advantages IMAP protocol has over POP3 protocol is the ability to search.

There are several ways of performing search using Mail.dll .NET IMAP library:

  • Search(Flag) – for common flag searches (seen, unseen, …).
  • SimpleImapQuery – easy one object query, where all conditions are joined with an AND operator.
  • Expression syntax – most advanced, allows using AND and OR operators and sorting.

IMAP search is done entirely on the server side, which means that it’s fast and doesn’t require Mail.dll client to download much data over the network.

Installation

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

PM> Install-Package Mail.dll

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

Connect to IMAP

Let’s start with the basics: we’ll connect to the IMAP server in .NET app and authenticate:

// C# code:

using (Imap imap = new Imap())
{
    imap.ConnectSSL("imap.example.com");
    imap.UseBestLogin("user", "password");
    imap.SelectInbox();

    // Search code goes here

    imap.Close();
}
' VB.NET code:

Using imap As New Imap()
    imap.ConnectSSL("imap.example.com")
    imap.UseBestLogin("user", "password")
    imap.SelectInbox()

    ' Search code here

    imap.Close()
End Using

When using Gmail you can use application passwords, with Office 365 you’ll need to use OAuth 2.0 to authenticate.

Mail.dll fully supports OAuth 2.0 for authentication, you can find OAuth2 samples for Office365 and Gmail on the Mail.dll samples page.

Search(Flag)

Now, let’s look at the search code. The first and the simplest way to search is by using Imap.Search(Flag) method. This sample below finds all unseen email messages (those that have \UNSEEN flag).

// C#

List<long> uidList = imap.Search(Flag.Unseen);

// now download each message and get the subject
foreach (long uid in uidList)
{
    IMail message = new MailBuilder()
        .CreateFromEml(imap.GetMessageByUID(uid));

    string subject = message.Subject;
}
' VB.NET

Dim uidList As List(Of Long) = imap.Search(Flag.Unseen)

' now download each message and get the subject
For Each uid As Long In uidList
	Dim message As IMail = New MailBuilder()_
		.CreateFromEml(imap.GetMessageByUID(uid))

	Dim subject As String = message.Subject
Next

SimpleImapQuery

Second approach is to use an IMAP query object. The sample below searches for all unseen emails with a certain subject. All non-null SimpleImapQuery properties are combined using and operator.

// C#

SimpleImapQuery query = new SimpleImapQuery();
query.Subject = "subject to search";
query.Unseen = true;

List<long> uids = imap.Search(query);
' VB.NET

Dim query As New SimpleImapQuery()
query.Subject = "subject to search"
query.Unseen = True

Dim uids As List(Of Long) = imap.Search(query)

Expression syntax

Finally, the most advanced search option using Expression class. You can use AND, OR and NOT operators in your IMAP search.

Note that Mail.dll fully encapsulates IMAP search syntax, with easy to use and very readable .NET classes:

// C#

List<long> uids = imap.Search().Where(
    Expression.And(
        Expression.Not(Expression.Subject("subject not to search")),
        Expression.HasFlag(Flag.Unseen)));
' VB.NET

Dim uids As List(Of Long) = imap.Search().Where(_
    Expression.[And](_
        Expression.[Not](Expression.Subject("subject not to search")),_
        Expression.HasFlag(Flag.Unseen)))

Expression syntax with sorting

Expression search syntax also allows sorting (defined in RFC 5256).

This feature is not available for every IMAP server: you need to check if your IMAP server supports ImapExtension.Sort extension first.

// C#

List<long> uids = imap.Search()
    .Where(Expression.And(
            Expression.Not(Expression.Subject("subject not to search")),
            Expression.HasFlag(Flag.Unseen)))
    .Sort(SortBy.Multiple(
            SortBy.Date(),
            SortBy.Subject()));
' VB.NET

Dim uids As List(Of Long) = imap.Search() _
    .Where(Expression.[And]( _
        Expression.[Not](Expression.Subject("subject not to search")), _
        Expression.HasFlag(Flag.Unseen))) _
    .Sort(SortBy.Multiple( _
        SortBy.[Date](), _
        SortBy.Subject()))
)

Notice the neat trick in Mail.dll .NET client, that allows casting FluentSearch class, received from imap.Search() method, to List<longs>:

public static implicit operator List<long>(FluentSearch search)
{
        return search.GetList();
}

We tend to use it very often for builder objects used in our unit tests.

Suggested reading

If you like it just give it a try and download it at: Mail.dll .NET IMAP component


Get Mail.dll

The post How to search IMAP in .NET first appeared on Blog | Limilabs.

]]>
https://www.limilabs.com/blog/how-to-search-imap-in-net/feed 36
Save all attachments to disk using IMAP https://www.limilabs.com/blog/save-all-attachments-to-disk-using-imap https://www.limilabs.com/blog/save-all-attachments-to-disk-using-imap#comments Fri, 28 Jul 2023 15:41:29 +0000 http://www.limilabs.com/blog/?p=1232 Unlock the potential of efficient email processing in .NET with this comprehensive guide on saving email attachments using Mail.dll’s IMAP component and IMAP protocol. In this article, we’ll walk you through the step-by-step process of downloading email messages using Mail.dll’s IMAP component and, more importantly, demonstrate how to effortlessly save all attachments to your disk. […]

The post Save all attachments to disk using IMAP first appeared on Blog | Limilabs.

]]>
Unlock the potential of efficient email processing in .NET with this comprehensive guide on saving email attachments using Mail.dll’s IMAP component and IMAP protocol.

In this article, we’ll walk you through the step-by-step process of downloading email messages using Mail.dll’s IMAP component and, more importantly, demonstrate how to effortlessly save all attachments to your disk.

Email MIME structure

The first thing you need to know is that email attachments are tightly integrated with the email message itself, ensuring that they are conveniently stored and transport together.

In MIME (Multipurpose Internet Mail Extensions), email attachments are stored together with an email message to ensure a structured and standardized way of transmitting and receiving email content with multiple parts.

The primary reason for storing attachments within the email message is to maintain a single cohesive entity that encapsulates all the components of the email, including its text, formatting, and any attached files. By bundling attachments with the message, the entire email becomes a self-contained package, making it easier to handle and process by email clients and servers.

Attachments in Mail.dll

Invoking Imap.GetMessageByUID method is going to download entire email message, including all attachments.

Attachments are stored within the email as part of a mime tree. Usually Quoted-Printable or Base64 encoding is used.

However, with Mail.dll, you don’t need to worry about navigating this mime tree yourself. The library efficiently parses the email’s structure, effortlessly exposing all attachments as familiar .NET collections. This user-friendly approach simplifies the process of handling email attachments, allowing you to focus on building robust and efficient email management solutions with ease.

There are 4 collections that contain attachments:

  • IMail.Attachments – all attachments (includes Visuals, NonVisuals and Alternatives).
  • IMail.Visuals – visual elements, files that should be displayed to the user, such as images embedded in an HTML email.
  • IMail.NonVisuals – non visual elements, “real” attachments.
  • IMail.Alternatives – alternative content representations, for example ical appointment.

How to download all email attachments in .NET

To retrieve all attachments from an email, you can take advantage of the IMail.Attachments collection provided by Mail.dll. This collection serves as a comprehensive repository, housing all the attachments associated with the email.

Each attachment is represented by a dedicated MimeData object, which encapsulates the specific data and metadata of the attachment.

Using the IMail.Attachments collection eliminates the need for manual traversal of the email’s mime tree or deciphering complex structures. Instead, Mail.dll handles the heavy lifting for you, ensuring a streamlined and user-friendly experience when accessing email attachments programmatically.

Installation

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 emails and all attachments

The C# code to download all emails and save all attachments using Mail.dll and IMAP is as follows.

using Limilabs.Client.IMAP;
using Limilabs.Mail;
using Limilabs.Mail.MIME
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        using(Imap imap = new Imap())
        {
            imap.ConnectSSL("imap.example.com");
            imap.UseBestLogin("user", "password");

            imap.SelectInbox();
            List<long>; uids = imap.Search(Flag.Unseen);
            foreach (long uid in uids)
            {
                var eml = imap.GetMessageByUID(uid);
                IMail email = new MailBuilder()
                    .CreateFromEml(eml);
                Console.WriteLine(email.Subject);

                foreach (MimeData mime in email.Attachments)
                {
                    mime.Save(@"c:\" + mime.SafeFileName);
                }
            }
            imap.Close();
        }
    }
};

Below is the VB.NET code for your reference:

Imports Limilabs.Client.IMAP
Imports Limilabs.Mail
Imports Limilabs.Mail.MIME
Imports System
Imports System.Collections.Generic

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.ConnectSSL("imap.example.com")
            imap.UseBestLogin("user", "password")

            imap.SelectInbox()
            Dim uids As List(Of Long) = imap.Search(Flag.Unseen)

            For Each uid As Long In uids
                Dim eml = imap.GetMessageByUID(uid)
                Dim email As IMail = New MailBuilder() _
                    .CreateFromEml(eml)
                Console.WriteLine(email.Subject)

                For Each mime As MimeData In email.Attachments
                    mime.Save("c:\" + mime.SafeFileName)
                Next
            Next
            imap.Close()
        End Using

    End Sub
End Module

Accessing attachment data

You can also save attachment to a specific stream using MimeData.Save(Stream stream).

You can get direct access to attachment binary data with MimeData.GetMemoryStream().

Finally you can get a byte array (byte[]) using MimeData.Data property.

Downloading only parts of the message

IMAP protocol provides very useful features in regard to working with attachments and all are available in Mail.dll .NET IMAP component.

With Mail.dll you can download only parts of email message, which in conjunction with getting basic email information without downloading entire message can make your code extremely fast.

Process emails embedded as attachments

In some situations you’ll receive a message that has another message attached.

You can use Mail.dll to extract all attachments from such inner messages no matter how deep the embedding level is.


Get Mail.dll

The post Save all attachments to disk using IMAP first appeared on Blog | Limilabs.

]]>
https://www.limilabs.com/blog/save-all-attachments-to-disk-using-imap/feed 10
Authenticate using Gmail’s App Passwords to IMAP, POP3 and SMTP https://www.limilabs.com/blog/using-app-passwords-with-gmail Thu, 27 Jul 2023 14:45:20 +0000 https://www.limilabs.com/blog/?p=5552 An app password is a 16-digit passcode that serves as an alternative authentication method, granting Mail.dll .NET IMAP, POP3 or SMTP client access to your Gmail Account with the same level of security as using a regular password. Your primary password can’t be used to authenticate anymore, because of Gmail’s secure access policies. Gmail introduced […]

The post Authenticate using Gmail’s App Passwords to IMAP, POP3 and SMTP first appeared on Blog | Limilabs.

]]>
An app password is a 16-digit passcode that serves as an alternative authentication method, granting Mail.dll .NET IMAP, POP3 or SMTP client access to your Gmail Account with the same level of security as using a regular password.

Your primary password can’t be used to authenticate anymore, because of Gmail’s secure access policies. Gmail introduced app passwords as a means to enhance account security.

This unique 16-digit passcode acts as a one-time key, eliminating the need to share your primary Google Account password with the application.

By generating an app password, users can rest assured that their sensitive credentials remain protected, and the Mail.dll .NET client can seamlessly interact with your Gmail Account, enabling efficient email management without compromising security.

OAuth 2.0 alternative

In many cases OAuth 2.0 is a better, but more complex option to access IMAP, POP3 and SMTP:

Enable 2-Step verification

Gmail’s App passwords can only be used with accounts that have 2-Step Verification turned on.

First go to your Google Account and on the left navigation panel, choose Security.

On the “Signing in to Google” panel:

  • Make sure I that 2-Step Verification is turned on
  • Finally choose App Passwords:

Generate new App password

On the “App password” screen select device and choose the device you’re using.

Then click Generate to create a new password:

New password will be generated – ready to use with Mail.dll clients.

Remember to copy the new password, because it won’t be displayed again:

Now you are ready to log in to your IMAP, SMTP, POP3 account using your email and the generated password (instead of your email’s primary password).

Authenticate using IMAP component

Mail.dll .NET email library provides a secure and efficient way to access email accounts, manage and parse email messages. It is a powerful .NET library that simplifies the implementation of IMAP functionality in various .NET applications.

We’ll use IMAP .NET client in an example below. Note that same password can be used for POP3 .NET client and SMTP .NET clients in exactly the same way.

Remember not to include any spaces when coping the app password to IMAP client’s authentication method, because authentication will fail.

C# code:

using (Imap client = new Imap()) 
{ 
    client.ConnectSSL("imap.gmail.com"); 
    client.UseBestLogin("XXXXX@gmail.com", "kvrcdzlicajaupje"); 

    // ... 

    client.Close(); 
}

VB.NET code:

Using imap As New Imap 
    imap.ConnectSSL("imap.gmail.com") 
    imap.UseBestLogin("XXXXX@gmail.com", "kvrcdzlicajaupje") 

    ' ... 

    imap.Close() 
End Using

Suggested reading


Get Mail.dll

The post Authenticate using Gmail’s App Passwords to IMAP, POP3 and SMTP first appeared on Blog | Limilabs.

]]>
Office 365: Basic Auth is disabled https://www.limilabs.com/blog/office-365-basic-auth-is-disabled Tue, 18 Oct 2022 17:45:46 +0000 https://www.limilabs.com/blog/?p=6350 Since October 2022 Basic Auth is by default disabled for IMAP and POP3 in Exchange Online / Office 365. Microsoft recommends using OAuth 2.0. This is not a big problem for Mail.dll email client for .net users as it support OAuth 2.0 in full. Auth 2.0 You should switch to OAuth 2.0 for authentication purposes: […]

The post Office 365: Basic Auth is disabled first appeared on Blog | Limilabs.

]]>

Since October 2022 Basic Auth is by default disabled for IMAP and POP3 in Exchange Online / Office 365. Microsoft recommends using OAuth 2.0. This is not a big problem for Mail.dll email client for .net users as it support OAuth 2.0 in full.

Auth 2.0

You should switch to OAuth 2.0 for authentication purposes:

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

Re-enable Basic Auth

For some time it was possible to re-enable Basic Auth for IMAP and POP3 for your tenant – it is no longer possible to do that.

The post Office 365: Basic Auth is disabled first appeared on Blog | Limilabs.

]]>
Office 365: OAuth 2.0 IMAP, POP3 email client connectivity tools https://www.limilabs.com/blog/office-365-oauth-2-0-imap-pop3-email-client-connectivity-tools Wed, 21 Sep 2022 15:35:07 +0000 https://www.limilabs.com/blog/?p=6298 To assist IT managers in resolving Office 365 connectivity issues, Microsoft offers a web-based connectivity analyzer. It works with POP3 or IMAP clients and OAuth 2.0: Test IMAP access:https://testconnectivity.microsoft.com/tests/O365Imap/input Test POP3 access:https://testconnectivity.microsoft.com/tests/O365Pop/input Those tools test IMAP and POP3 connectivity only – remember that application in your AD must be properly configured. You need to choose […]

The post Office 365: OAuth 2.0 IMAP, POP3 email client connectivity tools first appeared on Blog | Limilabs.

]]>
To assist IT managers in resolving Office 365 connectivity issues, Microsoft offers a web-based connectivity analyzer. It works with POP3 or IMAP clients and OAuth 2.0:

Test IMAP access:
https://testconnectivity.microsoft.com/tests/O365Imap/input

Test POP3 access:
https://testconnectivity.microsoft.com/tests/O365Pop/input

Those tools test IMAP and POP3 connectivity only – remember that application in your AD must be properly configured.

You need to choose and implement one of the available OAuth 2.0 flows:
https://www.limilabs.com/blog/office-365-basic-auth-is-disabled

The post Office 365: OAuth 2.0 IMAP, POP3 email client connectivity tools first appeared on Blog | Limilabs.

]]>
Office 365: Prevent Basic Auth being disabled https://www.limilabs.com/blog/office-365-prevent-basic-auth-disabled Mon, 25 Jul 2022 22:07:13 +0000 https://www.limilabs.com/blog/?p=6256 Microsoft will be randomly disabling Basic Auth for some tenants before October 1st 2002, then after October 1 2022, they will disable Basic Auth for IMAP and POP3 regardless of their usage. For some time it was possible to re-enable Basic Auth for IMAP and POP3 for your tenant – – it is no longer […]

The post Office 365: Prevent Basic Auth being disabled first appeared on Blog | Limilabs.

]]>
Microsoft will be randomly disabling Basic Auth for some tenants before October 1st 2002, then after October 1 2022, they will disable Basic Auth for IMAP and POP3 regardless of their usage.

For some time it was possible to re-enable Basic Auth for IMAP and POP3 for your tenant –
it is no longer possible to do that anymore.

You can find more details here:
https://techcommunity.microsoft.com/t5/exchange-team-blog/basic-authentication-deprecation-in-exchange-online-time-s-up/ba-p/3695312

Switch to OAuth 2.0

You should switch to OAuth 2.0 for authentication purposes:

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

Below steps are deprecated

If you want to opt-out, read the article below:

https://techcommunity.microsoft.com/t5/exchange-team-blog/basic-authentication-and-exchange-online-september-2021-update/ba-p/2772210

…or you can go directly to the self-help diagnostic (use your tenant’s Global Admin account):

https://aka.ms/PillarEXOBasicAuth

It’ll bring up the diagnostic in the Microsoft 365 admin center (if you’re a tenant Global Admin).

Hit Run Tests:

….on the next screen you’ll be able to enable Basic Auth for IMAP or POP3:

For accounts that use shared infrastructure you’ll need to run those 2 powershell commands:

Connect-ExchangeOnline
Enable-OrganizationCustomization

The post Office 365: Prevent Basic Auth being disabled first appeared on Blog | Limilabs.

]]>
OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP https://www.limilabs.com/blog/oauth2-client-credential-flow-office365-exchange-imap-pop3-smtp Fri, 08 Jul 2022 10:23:20 +0000 https://www.limilabs.com/blog/?p=6211 In this series:   OAuth 2.0 with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 web flow with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 password grant with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 device flow with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP This article shows how to implement OAuth 2.0 client credential flow to access Office365 via IMAP, POP3 […]

The post OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP first appeared on Blog | Limilabs.

]]>
In this series:

 

This article shows how to implement OAuth 2.0 client credential flow to access Office365 via IMAP, POP3 using Mail.dll .net email client. This flow is particularly useful for daemon/service apps that need to monitor certain mailboxes, without any user interaction.

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

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

Add permissions to your application in the API permissions / Add a permission wizard:

Select APIs my organization uses and search for Office 365 Exchange Online:

…then click Application permissions:

For POP access, choose the POP.AccessAsApp permission.
For IMAP access, choose the IMAP.AccessAsApp permission.
For SMTP access, choose the SMTP.SendAsApp permission.

Remember to Grant admin consent:

Create an application secret in Certificates & secrets panel by clicking ‘New client secret’ button:

Note the secret value as it is shown only during creation.

Use Windows PowerShell on your machine to Register service principals in Exchange.

Set execution policy first:

Set-ExecutionPolicy RemoteSigned

Install ExchangeOnlineManagement module:

Install-Module -Name ExchangeOnlineManagement 
Import-Module ExchangeOnlineManagement 

Connect and log-in as an administrator (you’ll be prompted for password):

Connect-ExchangeOnline
 -UserPrincipalName your-admin-account@your-domain.onmicrosoft.com

For Exchange running in hybrid mode log-in using following code:

$lc = Get-Credential
Connect-ExchangeOnline -Credential $lc

Create service principal

New-ServicePrincipal
 -AppId <APPLICATION_ID>
 -ServiceId <OBJECT_ID> 
 [-Organization <ORGANIZATION_ID>]

You can find ApplicationId and ObjectId in Enterprise applications in your application’s Overview panel:

Make sure you use the Object ID from the Enterprise Application

Do not use the value from the App Registration screen. 

In our case:

New-ServicePrincipal
 -AppId 061851f7-08c0-40bf-99c1-ebd489c11f16
 -ServiceId 4352fc11-5c2f-4b0b-af40-447ff10664e8

Note: If you still get an error running the New-ServicePrincipal cmdlet after you perform these steps, it is likely due to the fact that the user doesn’t have enough permissions in Exchange online to perform the operation. By default this cmdlet is available to users assigned the Role Management role

Add permissions to a specific mailbox:

Add-MailboxPermission
 -Identity "<USER@your-domain.onmicrosoft.com>"
 -User <OBJECT_ID>
 -AccessRights FullAccess

In our case:

Add-MailboxPermission
 -Identity "AdeleV@your-domain.onmicrosoft.com"
 -User 4352fc11-5c2f-4b0b-af40-447ff10664e8
 -AccessRights FullAccess

Shared mailboxes

You need to use Add-MailboxPermission for every shared mailbox you need access to:

Add-MailboxPermission
 -Identity "shared@your-domain.onmicrosoft.com"
 -User <OBJECT_ID>
 -AccessRights FullAccess

Let’s code

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

// C#

string clientId = "Application (client) ID";    // 061851f7-...
string tenantId = "Directory (tenant) ID";
string clientSecret = "Client secret value";

string userName = "Username/email for mailbox";    // AdeleV@...

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)
    .Build();

string[] scopes = new string[] { 
    "https://outlook.office365.com/.default" 
};
' VB.NET

Dim clientId As String = "Application (client) ID" ' 061851f7-...
Dim tenantId As String = "Directory (tenant) ID"
Dim clientSecret As String = "Client secret value"

Dim userName As String = "Username/email for mailbox"  'AdeleV@...

Dim app = ConfidentialClientApplicationBuilder.Create(clientId) _
    .WithTenantId(tenantId) _
    .WithClientSecret(clientSecret) _
    .Build()

Dim scopes As String() = New String() { _
    "https://outlook.office365.com/.default" _
}

Now acquire an access token:

// C#

var result = await app.AcquireTokenForClient(scopes)
    .ExecuteAsync();

string accessToken = result.AccessToken;
' VB.NET

Dim result = Await app.AcquireTokenForClient(scopes).ExecuteAsync()
Dim accessToken As String = result.AccessToken

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

// C#

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();
} 
' VB.NET

Using client As Imap = New Imap()
    client.ConnectSSL("outlook.office365.com")
    client.LoginOAUTH2(userName, accessToken)

    client.SelectInbox()

    Dim uids As List(Of Long) = imap.Search(Flag.Unseen)
    For Each uid As Long In uids
        Dim email As IMail = New MailBuilder() _
            .CreateFromEml(imap.GetMessageByUID(uid))
        Dim subject As String = email.Subject
    Next

    client.Close()
End Using

SMTP

Microsoft started supporting client credential flow and SMTP recently.

SMTP requires SMTP.SendAsApp permission added to your AD application.

All other OAuth flows (webdesktoppassword grantdevice) support SMTP client access as well.

For SMTP non-OAuth2 access:

SMTP AUTH will still be available when Basic authentication is permanently disabled on October 1, 2022.” (https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online)

However Microsoft disables SMTP AUTH in all tenants in which it’s not being used.

Here’s how to enable SMTP AUTH:
https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission

Troubleshooting

1. Start with PowerShell commands:

Get-ServicePrincipal
Get-MailboxPermission -Identity "AdeleV@your-domain.onmicrosoft.com"

You should see following results:

Make sure the ServiceId is the same as the Object ID on the Enterprise Application screen (do not use the value from the App Registration screen)

Make sure the AppId is the same as the Application ID on the Enterprise Application screen

2. Check if you can connect to this account using IMAP and regular interactive flow:

https://www.limilabs.com/blog/office-365-oauth-2-0-imap-pop3-email-client-connectivity-tools

This proves you have IMAP access properly configured.

3. Check if you added correct permissions and have granted Admin consent for your domain.

4. Usually people use incorrect client/tenant ids/secrets – double check every single value you enter (also for additional spaces).

5. You may need to wait 20-30 minutes for some changes to take effect (it really may take this long!).

Additional links

https://docs.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-and-maintain-the-exo-v2-module
https://docs.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-imap-and-pop-connections


Get Mail.dll

The post OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP first appeared on Blog | Limilabs.

]]>
OAuth 2.0 web flow with Office365/Exchange IMAP/POP3/SMTP https://www.limilabs.com/blog/oauth2-web-flow-office365-exchange-imap-pop3-smtp Wed, 30 Mar 2022 10:04:28 +0000 https://www.limilabs.com/blog/?p=6049 In this series:   OAuth 2.0 with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 web flow with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 password grant with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 device flow with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP This article shows how to implement OAuth 2.0 web flow to access Office365 via IMAP, POP3 or […]

The post OAuth 2.0 web flow with Office365/Exchange IMAP/POP3/SMTP first appeared on Blog | Limilabs.

]]>
In this series:

 

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

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

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

RedirectUri

Add an authentication redirect uri to your application:

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:

Create an app secret and remember its value:

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 clientSecret = "Client secret value";

// for @outlook.com/@hotmail accounts instead of setting .WithTenantId use:
// .WithAuthority(AadAuthorityAudience.PersonalMicrosoftAccount)

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)
    .WithRedirectUri("http://localhost/myapp/")
    .Build();
// This allows saving access/refresh tokens to some storage
TokenCacheHelper.EnableSerialization(app.UserTokenCache);

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",
};

In addition, you should request offline_access scope. When a user approves the offline_access scope, your app can receive refresh tokens from the Microsoft identity platform token endpoint. Refresh tokens are long-lived. Your app can get new access tokens as older ones expire.

Now try finding account by an identifier (it will be null on first access) in MSAL cache:

string userName;
string accessToken;

string identifier = null;

var account = await app.GetAccountAsync(identifier);

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

    userName = refresh.Account.Username;
    accessToken = refresh.AccessToken;

}
catch (MsalUiRequiredException e)
{
    // no token cache entry - perform authentication:

    Uri msUri = await app
        .GetAuthorizationRequestUrl(scopes)
        .ExecuteAsync();

    // Add a redirect code to the above 
    // Microsoft authentication uri and end this request.
}

On the first run user will be redirected to the msUri and will see a Microsoft login screen, with option to log-in, using a known account and granting access to the app (if needed):

After successful authentication Microsoft will redirect user’s browser back to your application – to the app’s RedirectUri (in our case http://localhost/MyApp/):

http://localhost/myapp/?code=0.Aa…AA&client_info=ey…I0In0&session_state=4dd….4488c8#

Controller responsible for handling this request should retrieve code parameter

string code = "get from url after redirect";

AuthenticationResult result = await app
    .AcquireTokenByAuthorizationCode(scopes, code)
    .ExecuteAsync();

string identifier = result.Account.HomeAccountId.Identifier;
string userName = result.Account.Username;
string accessToken = result.AccessToken;

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();
} 

Any organization and personal accounts

To access accounts from any organization and personal accounts as well, you need to specify correct account types when you create the App in your AD:

Additionally you need to use:    

    .WithAuthority(
        AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount
        )

instead of

    .WithTenantId(tenantId)

when creating the app:

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithAuthority(
        AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount
        )
    .WithClientSecret(clientSecret)
    .WithRedirectUri("http://localhost/myapp/")
    .Build();

Token serialization

Below is a simple implementation that saves MSAL token cache to file:

static class TokenCacheHelper
{
    public static void EnableSerialization(ITokenCache tokenCache)
    {
        tokenCache.SetBeforeAccess(BeforeAccessNotification);
        tokenCache.SetAfterAccess(AfterAccessNotification);
    }

    private static readonly string _fileName = "msalcache.bin3";

    private static readonly object _fileLock = new object();


    private static void BeforeAccessNotification(TokenCacheNotificationArgs args)
    {
        lock (_fileLock)
        {
            byte[] data = null;
            if (File.Exists(_fileName))
                data = File.ReadAllBytes(_fileName);
            args.TokenCache.DeserializeMsalV3(data);
        }
    }

    private static void AfterAccessNotification(TokenCacheNotificationArgs args)
    {
        if (args.HasStateChanged)
        {
            lock (_fileLock)
            {
                byte[] data = args.TokenCache.SerializeMsalV3();
                File.WriteAllBytes(_fileName, data);
            }
        }
    }
};

Please note that most likely you should store this cache in an encrypted form in some kind of a database.
Consider using MSAL token serialization implementations available here:

https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization


Get Mail.dll

The post OAuth 2.0 web flow with Office365/Exchange IMAP/POP3/SMTP first appeared on Blog | Limilabs.

]]>
Office365: Client Credential Flow support for POP/IMAP is coming in June 2022 https://www.limilabs.com/blog/office365-client-credential-flow-pop-imap-coming-june-2022 Tue, 29 Mar 2022 12:13:53 +0000 https://www.limilabs.com/blog/?p=6032 [Update] Client credential flow is now supported: https://www.limilabs.com/blog/oauth2-client-credential-flow-office365-exchange-imap-pop3-smtp Microsoft is working on bringing OAuth Client Credential Flow support for POP/IMAP for Office365/Exchange. It’s planned to be released in June 2022: https://www.microsoft.com/en-us/microsoft-365/roadmap?filters=&searchterms=70577 Check out currently supported OAuth 2.0 flows OAuth 2.0 with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 password grant with Office365/Exchange IMAP/POP3/SMTP OAuth 2.0 device flow with […]

The post Office365: Client Credential Flow support for POP/IMAP is coming in June 2022 first appeared on Blog | Limilabs.

]]>
[Update]

Client credential flow is now supported:

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


Microsoft is working on bringing OAuth Client Credential Flow support for POP/IMAP for Office365/Exchange. It’s planned to be released in June 2022:

https://www.microsoft.com/en-us/microsoft-365/roadmap?filters=&searchterms=70577

Check out currently supported OAuth 2.0 flows

The post Office365: Client Credential Flow support for POP/IMAP is coming in June 2022 first appeared on Blog | Limilabs.

]]>