Quantcast
Channel: Blog | Limilabs
Viewing all 120 articles
Browse latest View live

Replace attachments in email message

$
0
0

Attachments are not stored separately from message text and headers – they are embedded inside an email message. This, along with inefficient Base64 encoding is the most important reason of email messages being large in size. Mail.dll provides an easy way to replace attachments in existing messages:

// C#

IMail email = new MailBuilder().CreateFromEml(eml);
email.ReplaceAttachments();

' VB.NET

Dim email As IMail = New MailBuilder().CreateFromEml(eml)
email.ReplaceAttachments()

Each attachment will be replaced with the following text information: “This file (‘[FileName]‘) containing [Size] bytes of data was removed.”. Thus making email much smaller in size.

ReplaceAttachmentsmethod has an overloaded version, that allows you to skip visual elements (content-disposition: inline) or/and alternative email representations. It also allows to specify text template and custom Tag, that can be used, for example, to create a custom url. This url can point to a place to which attachment was moved.

Within the template you can use [FileName], [Size] and [Tag] as template placeholders.

// C#

IMail email = Limilabs.Mail.Fluent.Mail
    .Text("body")
    .AddAttachment(new byte[] { 1, 2, 3 })
    .SetFileName("report.pdf")
    .Create();

AttachmentReplacerConfiguration configuration = new AttachmentReplacerConfiguration();
configuration.ReplaceVisuals = false;
configuration.Tag = 
    att => "http://example.com/" + email.MessageID + "/" + att.FileName;
configuration.Template = 
    "Attachment [FileName] removed. You can download it here: [Tag]";

email.ReplaceAttachments(configuration);
' VB.NET

Dim email As IMail = Limilabs.Mail.Fluent.Mail _
    .Text("body") _
    .AddAttachment(New Byte() {1, 2, 3}) _
    .SetFileName("report.pdf") _
    .Create()

Dim configuration As New AttachmentReplacerConfiguration()
configuration.ReplaceVisuals = False
configuration.Tag = Function(att)
    Return "http://example.com/" + email.MessageID + "/" + att.FileName
    End Function
configuration.Template = _
    "Attachment [FileName] removed. You can download it here: [Tag]"

email.ReplaceAttachments(configuration)

The following example illustrates the full process of downloading email from IMAP server,
creating new email, with the same information, but with all attachments replaced, uploading this message, and deleting original one:

// C#

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

    foreach (long uid in imap.GetAll())
    {
        string eml = imap.GetMessageByUID(uid);
        IMail email = new MailBuilder().CreateFromEml(eml);
        if (email.Attachments.Count > 0)
        {
            email.ReplaceAttachments();

            imap.UploadMessage(email);

            imap.DeleteMessageByUID(uid);
        }
    }
    imap.Close();
}
' VB.NET

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

   For Each uid As Long In imap.GetAll()
      Dim eml As String = imap.GetMessageByUID(uid)
      Dim email As IMail = New MailBuilder().CreateFromEml(eml)
      If email.Attachments.Count > 0 Then
         email.ReplaceAttachments()

         imap.UploadMessage(email)

         imap.DeleteMessageByUID(uid)
      End If
   Next
   imap.Close()
End Using

Outlook.com IMAP national characters ENVELOPE bug

$
0
0

Summary

Outlook.com IMAP implementation does not work correctly with messages containing national characters. ENVELOPE retrieved for a message, that has national characters in the subject (correctly encoded using Base64), has ‘?’ characters instead of encoded characters.

Actual:
ENVELOPE ("Fri, 27 Sep 2013 17:59:48 +0200" "za????"

Expected:
ENVELOPE ("Fri, 27 Sep 2013 18:23:23 +0200" "=?utf-8?B?emHFvMOzxYLEhw==?=" ...
-or-
ENVELOPE ("Fri, 27 Sep 2013 18:21:17 +0200" "=?ISO-8859-2?B?emG/87Pm?=" ...

Logs

Mail.dll C: 6d9d6c00b9294efb APPEND Inbox (\SEEN) {243}
Mail.dll S: + Ready
Mail.dll C: Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0
Subject: =?utf-8?B?emHFvMOzxYLEhw==?=
Message-ID:
Date: Fri, 27 Sep 2013 17:59:48 +0200

Hello
Mail.dll S: 6d9d6c00b9294efb OK APPEND completed
Mail.dll C: 0a55ca5702664b94 UID FETCH 100065 (UID RFC822.SIZE INTERNALDATE FLAGS ENVELOPE BODYSTRUCTURE)
Mail.dll S: * 3 FETCH (UID 100065 RFC822.SIZE 290 FLAGS (\Seen) INTERNALDATE "27-Sep-2013 15:59:44 +0000" ENVELOPE ("Fri, 27 Sep 2013 17:59:48 +0200" "za????" NIL NIL NIL NIL NIL NIL NIL "") BODYSTRUCTURE ("TEXT" "plain" ("charset" "utf-8") NIL NIL "7BIT" 5 1 NIL NIL NIL NIL))
Mail.dll S: 0a55ca5702664b94 OK FETCH Completed

Workaround

You can workaround this issue, requesting subject header explicitly or downloading all headers (using GetHeadersByUID):

string eml = client.GetSpecificHeadersByUID(uploaded, new[]{"subject"}).EmlData;
string subject = new MailBuilder().CreateFromEml(eml).Subject;

Although slower, correct data is returned:


66496df367914917 UID FETCH 100078 (UID BODY[HEADER.FIELDS (SUBJECT)])
Mail.dll: 13 19:38:29 S: * 7 FETCH (UID 100078 BODY[HEADER.FIELDS ("SUBJECT")] {41}
Mail.dll: 13 19:38:30 S: Subject: =?utf-8?B?emHFvMOzxYLEhw==?=

Mail.dll: 13 19:38:30 S: )
Mail.dll: 13 19:38:30 S: 66496df367914917 OK FETCH Completed

SSL vs TLS vs STARTTLS

$
0
0

There’s often quite a confusion about the different terms: SSL, TLS, STARTTLS and STLS.

SSL and TLS

SSL and TLS are cryptographic protocols, both provide a way to encrypt communication channel between two machines over the Internet (e.g. client computer and a server). SSL stands for Secure Sockets Layer and current version is 3.0. TLS stands for Transport Layer Security and the current version is 1.2. TLS is the successor to SSL. The terms SSL and TLS can be used interchangeably, unless you’re referring to a specific protocol version.

Version numbering is inconsistent between SSL and TLSs. When TLS took over SSL as the preferred protocol name, it began with a new version number. The ordering of protocols in terms of oldest to newest is: SSLv2, SSLv3, TLSv1.0, TLSv1.1, TLSv1.2.

STARTTLS and STLS

STARTTLS is a protocol command, that is issued by an email client. It indicates, that the client wants to upgrade existing, insecure connection to a secure connection using SSL/TLS cryptographic protocol. STARTTLS command name is used by SMTP and IMAP protocols, whereas POP3 protocol uses STLS as the command name.

Despite having TLS in the name, STARTTLS doesn’t mean TLS will be used. Both SSL and TLS are acceptable protocols for securing the communication.

Clear text/Plain text

No security protocol is used at all. All commands, responses and data are transferred in plain text.

client.Connect("mail.example.com");

Implict SSL mode

Implict SSL mode means, that you connect to SSL/TLS encrypted port.

client.ConnectSSL("mail.example.com");

Explicit SSL mode

Explicit SSL mode means, that you connect to plaint text port and secure the connection by issuing STARTTLS (or STLS) command afterwards (you explicitly secure the connection).

client.Connect("mail.example.com");
client.StartTLS();

Securing the connection

Regardless of whether you use implict (connecting to an SSL/TLS encrypted port) or explicit (using STARTTLS to upgrade an existing connection) mode, both sides will negotiate which protocol and which version to use. This negotiation is based on how client and server have been configured and what each side supports.

SSL/TLS support

Support for SSL/TLS is virtually universal, however which versions are supported is variable. Pretty much everything supports SSLv3. Most machines support TLSv1.0.

TLS vs STARTTLS naming problem

One significant complicating factor is that some email software incorrectly uses the term TLS when they should have used “STARTTLS” or “explicit SSL/TLS”. Older versions of Thunderbird used “TLS” to mean “enforce use of STARTTLS to upgrade the connection, and fail if STARTTLS is not supported” and “TLS, if available” to mean “use STARTTLS to upgrade the connection, if the server advertises support for it, otherwise just use an insecure connection” (very problematic, as we’ll see below).

Port numbers

To add security to some existing protocols (IMAP, POP3, SMTP), it was decided to just add SSL/TLS encryption as a layer underneath the existing protocol. However to distinguish that software should talk the SSL/TLS encrypted version of the protocol rather than the plaintext one, a different port number was used for each protocol:

Protocol Plain text SSL
IMAP 143 993
POP3 110 995
SMTP 587 or 25 465

Too many ports? Solution: Plain text + STARTTLS

At some point, it was decided that having 2 ports for every protocol was wasteful, and instead it’s better to have 1 port, that starts off as plain text, but clients can upgrade the connection to an SSL/TLS encrypted one using STARTTLS (or STLS for POP3 protocol) command.

STARTTLS problems

There were a few problems with this. There exists lots of software, that used the alternate port numbers with pure SSL/TLS connections. Client software can be very long lived, so you can’t just disable the encrypted ports until all software has been upgraded.

Each protocol received mechanisms to tell clients that the server supported upgrading to SSL/TLS (e.g. STARTTLS in IMAP’s CAPABILITY response), and that they should not attempt to login without doing the STARTTLS upgrade (LOGINDISABLED in IMAP’s CAPABILITY response). This created two unfortunate situations:

  • Some software just ignored the “login disabled until upgraded” announcement (LOGINDISABLED, STARTTLS) and just tried to log in anyway, sending the user login name and password over clear text channel. The server rejected the login and password, but the details had already been sent over the Internet in plain text.
  • Other software saw the “login disabled until upgraded” announcement, but then wouldn’t upgrade the connection automatically, and thus reported login errors back to the user, which caused confusion about what was wrong.
    • Both of these problems resulted in significant compatibility issues with existing clients, and so most system administrators continued to just use plain text connections on one port, and encrypted connections on a separate port number.

      Disable plain text for IMAP and POP3

      Many companies (e.g. Gmail, Outlook.com) disabled plain IMAP (port 143) and plain POP3 (port 110), so people must use a SSL/TLS encrypted connection – this removes the need for having STARTTLS command completely.

      SMTP STARTTLS stays

      The one real exception to the above is SMTP. Most email software used SMTP on port 25 to submit messages to the email server for onward transmission to the destination. However SMTP was originally designed for transfer, not submission. So yet another port (587) was defined for message submission.

      Port 587 doesn’t mandate requiring STARTTLS, however the use of port 587 became popular around the same time as the realization that SSL/TLS encryption of communications between clients and servers was an important issue. The result is that most systems, that offer message submission over port 587 require clients to use STARTLS to upgrade the connection. Login and password to authenticate is also required.

      There has been an additional benefit to this approach as well. By moving users away from using port 25 for email submission, ISPs can block outgoing port 25 connections from users’ computers, which were a significant source of spam, due to user computers infected with spam sending viruses.

      Further reads

      Using SSL/TLS with IMAP
      Using SSL/TLS with SMTP
      Using SSL/TLS with POP3

Reading Outlook .msg file format in .NET

$
0
0

Files containing the .msg file extension are most commonly created by or saved from within one of the Microsoft Outlook email applications.

The MSG file contains information about a saved email file including the date of the message, the subject, who sent it, who received it and the contents of the email associated with the file. If attachments ares included with an email, that information will also be saved within the associated MSG file.

MsgConverter , than can be used to read .msg files, is written in pure .NET, it does not require registration or any other components or libraries (including Outlook).

The following code snippet reads .msg file in .NET and access its most common properties, such as subject, sender and attachments.

// C#

using (MsgConverter converter = new MsgConverter(@"c:\outlook1.msg"))
{
    if (converter.Type == MsgType.Note)
    {
        IMail email = converter.CreateMessage();

        Console.WriteLine("Subject: {0}", email.Subject);
        Console.WriteLine("Sender name: {0}", email.Sender.Name);
        Console.WriteLine("Sender address: {0}", email.Sender.Address);

        Console.WriteLine("Attachments: {0}", email.Attachments.Count);
        foreach (MimeData attachment in email.Attachments)
        {
            attachment.Save(@"c:\" + attachment.SafeFileName);
        }
    }
}
' VB.NET

Using converter As New MsgConverter("c:\outlook1.msg")
    If converter.Type = MsgType.Note Then
        Dim email As IMail = converter.CreateMessage()

        Console.WriteLine("Subject: {0}", email.Subject)
        Console.WriteLine("Sender name: {0}", email.Sender.Name)
        Console.WriteLine("Sender address: {0}", email.Sender.Address)
        
        Console.WriteLine("Attachments: {0}", email.Attachments.Count)
        For Each attachment As MimeData In email.Attachments
            attachment.Save("c:\" + attachment.SafeFileName)
        Next

    End If
End Using

You can read more on how to access To, Cc, Bcc fields.

Convert Outlook .msg file to MIME format in .NET

$
0
0

Files containing the .msg file extension are most commonly created by or saved from within one of the Microsoft Outlook email applications.

The MSG file contains information about a saved email file including the date of the message, the subject, who sent it, who received it and the contents of the email associated with the file. If attachments ares included with an email, that information will also be saved within the associated MSG file.

MsgConverter , than can be used to convert .msg files to MIME, is written in pure .NET, it does not require registration or any other components or libraries (including Outlook).

The following code snippet reads .msg file in .NET and saves it using MIME format to disk. MIME is shorthand for Multipurpose Internet Mail Extensions and is an Internet standard used to store and transport email messages.

// C#

using (MsgConverter converter = new MsgConverter(@"c:\outlook1.msg"))
{
    if (converter.Type == MsgType.Note)
    {
        IMail email = converter.CreateMessage();

	// Render message using MIME format to regular string
        string mime = email.RenderEml();

	// Save message to file using MIME message format
        email.Save(@"c:\mime.eml");
    }
}
' VB.NET

Using converter As New MsgConverter("c:\outlook1.msg")
If converter.Type = MsgType.Note Then
    Dim email As IMail = converter.CreateMessage()

	' Render message using MIME format to regular string
	Dim mime As String = email.RenderEml()

	' Save message to file using MIME message format
	email.Save("c:\mime.eml")
    End If
End Using

Search unanswered emails in Gmail

$
0
0

IMAP protocol in RFC3501 introduced \Answered flag. \Answered flag should mark messages that have been answered. This flag can by set by client applications or even by SMTP server, which can be examining In-Reply-To email headers.

Unfortunately if the message is answered through Gmail’s web interface, the \Answered flag will not be set. It will only be set if the messages were answered using an email program that sets this flag.

This means that \Answered flag can’t be used to find not-answered emails.

One option to resolve this problem is to use Gmail IMAP extensions, X-GM-THRID in particular.

We’ll connect to Gmail using IMAP – remember to use SSL and be sure to enable IMAP protocol for Gmail.

As we plan to search all emails, including sent and received ones, we’ll use CommonFolders class to get ‘All Mail’ folder.

Then we’ll get Envelope for each message. Envelope contains GmailThreadId property. It contains thread id to which this email was assigned to by Gmail.

Finally we’ll find threads that contain only one message – those are messages that were not answered.

// C#

using(Imap client = new Imap())
{
    client.ConnectSSL("imap.gmail.com");
    client.Login("pat@limilabs.com","password");

    // Select 'All Mail' folder.
    List<FolderInfo> folders = client.GetFolders();
    CommonFolders common = new CommonFolders(folders);
    client.Select(common.AllMail);

    // Get envelopes for all emails.
    List<long> uids = client.GetAll();
    List<Envelope> envelopes = client.GetEnvelopeByUID(uids);

    // Group messages by thread id.
    var threads = new Dictionary<decimal, List<Envelope>>();
    foreach (Envelope envelope in envelopes)
    {
        decimal threadId = (decimal) envelope.GmailThreadId;
        if (threads.ContainsKey(threadId) == false)
            threads[threadId] = new List<Envelope>();
        
        threads[threadId].Add(envelope);
    }

    // Find threads containing single message.
    foreach (KeyValuePair<decimal, List<Envelope>> pair in threads)
    {
        if (pair.Value.Count == 1)
        {
            Envelope envelope = pair.Value[0];
            Console.WriteLine("Gmail message id: {0}; subject: {1}", 
                envelope.GmailMessageId , 
                envelope.Subject);

        }
    }
    client.Close();
}
' VB.NET

Using client As New Imap()
	client.ConnectSSL("imap.gmail.com")
	client.Login("pat@limilabs.com", "password")

	' Select 'All Mail' folder.
	Dim folders As List(Of FolderInfo) = client.GetFolders()
	Dim common As New CommonFolders(folders)
	client.[Select](common.AllMail)

	' Get envelopes for all emails.
	Dim uids As List(Of Long) = client.GetAll()
	Dim envelopes As List(Of Envelope) = client.GetEnvelopeByUID(uids)

	' Group messages by thread id.
	Dim threads = New Dictionary(Of Decimal, List(Of Envelope))()
	For Each envelope As Envelope In envelopes
		Dim threadId As Decimal = CDec(envelope.GmailThreadId)
		If threads.ContainsKey(threadId) = False Then
			threads(threadId) = New List(Of Envelope)()
		End If

		threads(threadId).Add(envelope)
	Next

	' Find threads containing single message.
	For Each pair As KeyValuePair(Of Decimal, List(Of Envelope)) In threads
		If pair.Value.Count = 1 Then
			Dim envelope As Envelope = pair.Value(0)

			Console.WriteLine("Gmail message id: {0}; subject: {1}", _
				envelope.GmailMessageId, envelope.Subject)
		End If
	Next
	client.Close()
End Using

Upload email to Sent folder after sending

$
0
0

Some SMTP servers automatically put sent messages in the sent folder, but this is not a SMTP protocol requirement and many servers don’t do that.

In such case, you’ll need to manually upload message to the sent folder using IMAP. Unfortunately there is no standard that would allow checking, if SMTP server puts send messages in Sent folder.

Create email message

First we’ll create new email message:

// C#

IMail email = Limilabs.Mail.Fluent.Mail
    .Html(@"Html with an image: <img src=""cid:lena"" />")
    .AddVisual(@"c:\lena.jpeg").SetContentId("lena")
    .AddAttachment(@"c:\tmp.doc").SetFileName("document.doc")
    .To("to@example.com")
    .From("from@example.com")
    .Subject("Subject")
    .Create();
' VB.NET

Dim email As IMail = Mail _
    .Html("Html with an image: <img src=""cid:lena"" />") _
    .AddVisual("C:\lena.jpeg").SetContentId("lena") _
    .AddAttachment("C:\tmp.doc").SetFileName("document.doc") _
    .To("to@example.com") _
    .From("from@example.com") _
    .Subject("Subject") _
    .Create()

Send email message

Then we’ll send it using SMTP protocol:

// C#

SendMessageResult result;
using (Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.server.com");     // or ConnectSSL for SSL
    smtp.UseBestLogin("user", "password");

    result = smtp.SendMessage(email);

    smtp.Close();
}
' VB.NET

Dim result As SendMessageResult
Using smtp As New Smtp()
	smtp.Connect("smtp.server.com")     ' or ConnectSSL for SSL
	smtp.UseBestLogin("user", "password")

	result = smtp.SendMessage(email)

	smtp.Close()
End Using

Upload email message

Finally we’ll connect to IMAP server, get Sent folder and upload message to it:

// C#

if (result.Status == SendMessageStatus.Success)
{
    using (Imap imap = new Imap())
    {
        imap.Connect("imap.server.com");     // or ConnectSSL for SSL
        imap.UseBestLogin("user", "password");

        FolderInfo sent = new CommonFolders(imap.GetFolders()).Sent;
        imap.UploadMessage(sent, email);

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

If result.Status = SendMessageStatus.Success Then
	Using imap As New Imap()
		imap.Connect("imap.server.com")		' or ConnectSSL for SSL
		imap.UseBestLogin("user", "password")

		Dim sent As FolderInfo = New CommonFolders(imap.GetFolders()).Sent
		imap.UploadMessage(sent, email)

		imap.Close()
	End Using
End If

Entire code

Here’s the full code:

// C#

IMail email = Limilabs.Mail.Fluent.Mail
    .Html(@"Html with an image: <img src=""cid:lena"" />")
    .AddVisual(@"c:\lena.jpeg").SetContentId("lena")
    .AddAttachment(@"c:\tmp.doc").SetFileName("document.doc")
    .To("to@example.com")
    .From("from@example.com")
    .Subject("Subject")
    .Create();

SendMessageResult result;
using (Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.server.com");    // or ConnectSSL for SSL
    smtp.UseBestLogin("user", "password");

    result = smtp.SendMessage(email);

    smtp.Close();
}

if (result.Status == SendMessageStatus.Success)
{
    using (Imap imap = new Imap())
    {
        imap.Connect("imap.server.com");     // or ConnectSSL for SSL
        imap.UseBestLogin("user", "password");

        FolderInfo sent = new CommonFolders(imap.GetFolders()).Sent;
        imap.UploadMessage(sent, email);

        imap.Close();
    }
}

' VB.NET

Dim email As IMail = Mail _
    .Html("Html with an image: <img src=""cid:lena"" />") _
    .AddVisual("C:\lena.jpeg").SetContentId("lena") _
    .AddAttachment("C:\tmp.doc").SetFileName("document.doc") _
    .To("to@example.com") _
    .From("from@example.com") _
    .Subject("Subject") _
    .Create()

Dim result As SendMessageResult
Using smtp As New Smtp()
	smtp.Connect("smtp.server.com")	' or ConnectSSL for SSL
	smtp.UseBestLogin("user", "password")

	result = smtp.SendMessage(email)

	smtp.Close()
End Using

If result.Status = SendMessageStatus.Success Then
	Using imap As New Imap()
		imap.Connect("imap.server.com")		' or ConnectSSL for SSL
		imap.UseBestLogin("user", "password")

		Dim sent As FolderInfo = New CommonFolders(imap.GetFolders()).Sent
		imap.UploadMessage(sent, email)

		imap.Close()
	End Using
End If

EnvelopedCms decrypt problem

$
0
0

.NET’s EnvelopedCms class represents a CMS/PKCS #7 structure for enveloped data. Such data are for example used in S/MIME encrypted messages.

EnvelopedCms class contains several Decrypt method overloads:

  • Decrypt()
  • Decrypt(RecipientInfo)
  • Decrypt(X509Certificate2Collection)
  • Decrypt(RecipientInfo, X509Certificate2Collection)

Each Decrypt method decrypts the contents of the decoded enveloped CMS/PKCS #7 data. Each searches the current user and local machine My stores for the appropriate certificate and private key.

Last two overloads allow passing additional collection of X509 certificates, that should be searched to find matching certificate for decryption.

There are 2 most common errors that can occur while decrypting:

  • “The enveloped-data message does not contain the specified recipient.” – Which means that no matching certificate was found in My stores and in the additional certificate collection.
  • “Cannot find object or property.” – Certificate was found, but there is no private key in it, so it can not be used to decryped the enveloped data.

There are 3 ways of adding certificates to My store, 2 of those don’t import private key:

  • “Personal” tab in CertMgr (does not import private key).
  • MMC “Certificates” snap-in (“My user account”) (does not import private key).
  • Double clicking the pfx file (imports private key).

In many cases data are encrypted using 2 or more certificates (so both sender and receiver are able to decrypt the message)

The problem with all Decrypt methods is that they try to use only the first certificate they find. The matching is based on certificate SN. First, both My stores are search, then extra store (passed certificate collection).

This leads to a problem when, both certificates are in My store, but only one contains a private key.

.NET is going to use the first certificate it finds – if it’s the one without the private key, “Cannot find object or property” exception is going to be thrown.

The only workaround for this problem is to try to decrypt the message for each ReceipientInfo separately. This way we are sure that all certificates will be tried.

Mail.dll .NET secure email component does this automatically, so no additional code is required.


Access shared/delegate mailbox of Exchange Server

$
0
0

1. Enable IMAP and POP3 protocols

Make sure you have enabled IMAP and POP3. Following articles can help you with that:

2. Turn on basic authentication

Exchange Management Console

  • Open EMC, expand to Server Configuration->Client Access.
  • In the middle panel, click your exchange CAS server, click POP3 and IMAP4 tab, right click IMAP4 and choose properties.
  • In Authentication tab, select “Plain text logon (Basic authentication)”, then click OK.
  • Open services.msc, restart Microsoft Exchange Transport services.

Power Shell

Set-IMAPSettings -Server -LoginType PlainTextLogin
Set-POPSettings -Server -LoginType PlainTextLogin

Open services.msc, restart Microsoft Exchange Transport services.

3. Add permissions to the shared mailbox

Give one user full access permission to the shared mailbox:

Add-MailboxPermission Shared.Mailbox1 -user John.Doe -AccessRights FullAccess

Note: You cannot add permissions for user without mailbox, Powershell is the only option in such case.

4. Access the shared mailbox

Exchange 2003

Use the following user format DomainName\Username\MailboxAlias
(e.g. DOMAIN\John.Doe\Shared.Mailbox1) to log into the shared mailbox.

Exchange 2007

Install this patch: http://support.microsoft.com/?kbid=949926

Use the following user format DomainName\Username\MailboxAlias
(e.g. DOMAIN\John.Doe\Shared.Mailbox1) to log into the shared mailbox.

Exchange 2010, Exchange 2013

Use the following user format DomainName\Username\MailboxAlias
(e.g. DOMAIN\John.Doe\Shared.Mailbox1) to log into the shared mailbox.

NAMESPACE command

You can also try using NAMESPACE command to obtain information about shared/public folders.

LoginPLAIN login as different user

You can try 3 parameter of LoginPLAIN to log in as a different user:

using (Imap imap = new Imap)
{
    imap.Connect(); // or ConnectSSL for SSL

    imap.LoginPLAIN("user@example.com", "admin@example.com", "admin_password");

    //...

    imap.Close();
}

iCloud: IMAP and SMTP settings

$
0
0

iCloud supports access via IMAP and SMTP protocols, POP3 is not supported. Below you can find the configuration settings for those protocols.

Both (IMAP and SMTP) use implicit SSL (use ConnectSSL method) and explicit SSL (you can use Connect method and then secure the channel using StartTLS method)

IMAP

Server: imap.mail.me.com
SSL: true-implicit
Port: 993 (default)
User: pat (not pat@icloud.com)

SMTP

Server: smtp.mail.me.com
SSL: true-explicit
Port: 587 (default)
User: pat@icloud.com (not pat)

Following are the code samples for Mail.dll .NET IMAP, POP3 and SMTP component.

// C#

using (Imap client = new Imap())
{
    client.ConnectSSL("imap.mail.me.com");
    client.UseBestLogin("pat", "password");
    ...
}

using (Smtp client = new Smtp ())
{
    client.Connect("smtp.mail.me.com");
    client.StartTLS();
    client.UseBestLogin("pat@icloud.com", "password");
    ...
}
' VB.NET

Using client As New Imap()
	client.ConnectSSL("imap.mail.me.com")
	client.UseBestLogin("pat", "password")
	...
End Using

Using client As New Smtp()
	client.Connect("smtp.mail.me.com")
	client.StartTLS()
	client.UseBestLogin("pat@icloud.com", "password")
	...
End Using

Outlook.com IMAP looses attachment contents on COPY

$
0
0

Outlook.com IMAP looses attachment contents on COPY operation.

Coping an email with an attachment on Outlook.com using IMAP works correct for small attachments:

C: 7554e85569d0465d UID COPY 100828 "Destination"
S: 7554e85569d0465d OK [COPYUID 43582022 100828 100003] COPY completed

With large attachments (~3MB), although COPY command succeeds:

C: 7734b17263a84259 UID COPY 100823 "Destination"
S: 7734b17263a84259 OK [COPYUID 43582022 100823 100001] COPY completed

All contents of the attachments are removed by the server:

------_=_NextPart_001_01CF7412.6651E594
Content-Type: image/jpeg; name="100557_1_DSC_0041 (2).jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="100557_1_DSC_0041 (2).jpg"
MS-Blob-Excluded: messageId=7C7BA5A2-E006-11E3-94A8-2C59E5464128; blobId=0; encodedLength=2925184; resolveError=true; blobHash=F206EC6BB4B95BF30B1382C38A33C9BEC3DBFB4A

------_=_NextPart_001_01CF7412.6651E594--

After COPY operation email message is modified by the server:
- attachment contents are removed (attachment must be large enough ~3MB)
- new MIME header: MS-Blob-Excluded is added to the MIME entity representing the attachment.

All IMAP clients are affected.

It seems that this behavior is coded-in on purpose, however it’s a bug and violation of the IMAP protocol.

It would be much wiser to fail on COPY command with appropriate error message, if for some reason (performance?) the operation would result in loosing data.

Gmail doesn’t send “OK [UNSEEN n]” when required

$
0
0

In IMAP protocol OK [UNSEEN <n>] is a required untagged response to SELECT command. Core IMAP specification (RFC 3501) along with the errata states:

Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT
REQUIRED OK untagged responses: PERMANENTFLAGS,
UIDNEXT, UIDVALIDITY, UNSEEN (if any unseen exist)

and later:

If there are any unseen messages in the mailbox, an UNSEEN response MUST be sent, if not it MUST be omitted.

However Gmail IMAP server doesn’t send the OK [UNSEEN <n>] response, even when there are unseen emails in the mailbox. The following listing shows that (note the subsequent SEARCH command that returns a single email):

C: c7a56 SELECT "INBOX"
S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $Phishing $MDNSent NonJunk $NotPhishing Junk)
S: * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $Phishing $MDNSent NonJunk $NotPhishing Junk \*)] Flags permitted.
S: * OK [UIDVALIDITY 3] UIDs valid.
S: * 7619 EXISTS
S: * 0 RECENT
S: * OK [UIDNEXT 30566] Predicted next UID.
S: * OK [HIGHESTMODSEQ 2384884]
S: c7a56 OK [READ-WRITE] INBOX selected. (Success)
C: a7c39 UID SEARCH UNSEEN
S: * SEARCH 30565
S: a7c39 OK SEARCH completed (Success)

IMAP search requires parentheses

$
0
0

IMAP protocol uses Polish notation (also known as prefix notation) for client queries. In general it means, that operator (in case of IMAP search it’s always a logical operator) is placed left of its operands.

Polish notation

Expression that would be written in conventional infix notation as:
(5 − 6) * 7
can be written in prefix/Polish notation as:
* (− 5 6) 7
As all mathematical operands are binary (or have defined number of operands) we don’t need parentheses to correctly evaluate this expression:
* − 5 6 7

Polish notation doesn’t require parentheses.

IMAP search needs parentheses

Although IMAP search syntax uses Polish notation it actually requires parentheses to be evaluated unambiguously.

This is because there is no explicitly defined AND operator, that takes exactly 2 operands.

RFC 3501:

When multiple keys are specified, the result is the intersection (AND function) of all the messages that match those keys.

So although it is true that Polish and reverse Polish notations don’t require parentheses, it is not true that IMAP search doesn’t require them.

‘OR/AND’ example

Expression 1a:

Regular notation:
(SUBJECT subject OR BODY body) AND FROM from

Polish notation:
AND OR SUBJECT subject BODY body FROM from

IMAP’s Polish notation (note there is no AND operator):
OR SUBJECT subject BODY body FROM from

Expression 1b:

Regular notation:
SUBJECT subject OR (BODY body AND FROM from)

Polish notation:
OR SUBJECT subject AND BODY body FROM from

IMAP’s Polish notation (note there is no AND operator):
OR SUBJECT subject BODY body FROM from

1a != 1b

Expression 1a is not equal to Expression 1b:
((a or b) and c) != (a or (b and c))

For:
a = true
b = true
c = false

We have:
((true or true) and false) != (true or (true and false))
false != true

Parentheses are needed

But when there is no AND operator, IMAP’s Polish notations look exactly the same, thus we need parentheses!

Expression 1a (IMAP’s Polish notation with parentheses):
(OR SUBJECT subject BODY body) FROM from

Expression 1b (IMAP’s Polish notation with parentheses):
OR SUBJECT subject (BODY body FROM from)

‘NOT’ example

Expression 2a:

Regular notation:
NOT (SUBJECT subject AND BODY body)

Polish notation:
NOT AND SUBJECT subject BODY body

IMAP’s Polish notation (note there is no AND operator):
NOT SUBJECT subject BODY body

Expression 2b:

Regular notation:
(NOT SUBJECT subject) AND BODY body

Polish notation:
AND NOT SUBJECT subject BODY body

IMAP’s Polish notation (note there is no AND operator):
NOT SUBJECT subject BODY body

2a != 2b

Expression 2a is obviously not equal to Expression 2b.

Parentheses are needed

Again IMAP’s Polish notations look the same. We need parentheses!

Expression 2a (IMAP’s Polish notation with parentheses):
NOT (SUBJECT subject BODY body)

Expression 2b (IMAP’s Polish notation with parentheses):
(NOT SUBJECT subject) BODY body

IdeaImapServer IMAP search parentheses bug

$
0
0

IdeaImapServer doesn’t recognize parenthesis in IMAP search command.

RFC 3501 is clear:

A search key can also be a parenthesized list of one or more search keys (e.g., for use with the OR and NOT keys).

Please note that RFC document is not talking, if a server SHOULD or MUST support parentheses. It tells that any search key can always be a parenthesized list.

What is worth mentioning, although IMAP search uses polish notation (which doesn’t need parenthesis by itself) IMAP search command syntax actually requires parentheses.

UID SEARCH (OR SUBJECT subject BODY body) – fails, while:
UID SEARCH OR SUBJECT subject BODY body – succeeds.

This is the log from the server minus the authentication (note that 2nd search returns one email):


S: * OK serwer1476502.home.pl IdeaImapServer v0.80 ready
C: 21a04 CAPABILITY
S: * CAPABILITY IMAP4rev1 LITERAL+ CHILDREN I18NLEVEL=1 IDLE SORT UIDPLUS UNSELECT XLIST AUTH=PLAIN AUTH=LOGIN
C: 98104 UID SEARCH (OR SUBJECT subject BODY body)
S: 98104 BAD Unknown argument: (OR SUBJECT subject BODY body
C: 16e37 UID SEARCH OR SUBJECT subject BODY body
S: * SEARCH 1
S: 16e37 OK Completed

SENTBEFORE doesn’t work correctly on Yahoo IMAP server

$
0
0

Expression.SentBefore doesn’t work correctly on Yahoo IMAP server.

IMAP protocol equivalent of this expression is SENTBEFORE. It examines email’s Date: header.

It appears that although SENTSINCE doesn’t work, SENTSINCE (Expression.SentSince), BEFORE (Expression.Before) and SINCE (Expression.Since) do work correctly. BEFORE and SINCE use email’s INTERNALDATE recorded by the IMAP server instead of Date: header.

C: 0895789b79c64868 UID FETCH 14622 (UID RFC822.SIZE INTERNALDATE ENVELOPE)
S: * 1 FETCH (UID 14622
INTERNALDATE "10-Jun-2014 13:02:08 +0000"
ENVELOPE ("Wed, 10 Jun 2014 15:02:08 +0000" "test2" NIL NIL NIL NIL NIL NIL NIL NIL))
S: 0895789b79c64868 OK UID FETCH completed
C: 2b535791f07e4515 UID SEARCH BEFORE 12-Jun-2014
S: * SEARCH 14622
S: 2b535791f07e4515 OK UID SEARCH completed
C: b726a850e61c4082 UID SEARCH SENTBEFORE 12-Jun-2014
S: * SEARCH
S: b726a850e61c4082 OK UID SEARCH completed
C: 3e479e518dc04915 UID SEARCH BEFORE 13-Jun-2014
S: * SEARCH 14622
S: 3e479e518dc04915 OK UID SEARCH completed
C: 31b7f9ffbe4f4934 UID SEARCH SENTBEFORE 13-Jun-2014
S: * SEARCH
S: 31b7f9ffbe4f4934 OK UID SEARCH completed
C: 2fd2d29b90a24f16 LOGOUT
S: * BYE IMAP4rev1 Server logging out
S: 2fd2d29b90a24f16 OK LOGOUT completed

The fact is that Yahoo IMAP implantation is buggy. Once, the server assigned “17-Jan-1970 05:37:46 +0000″ as an INTERNALDATE to one of my emails, just to change that on the next login.


Yandex BODYSTRUCTURE CHARSET “X-UNKNOWN”

$
0
0

Yandex does not recognize UTF-8 charset correctly. For a message with text part using utf-8 charset:

Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

Yandex returns “X-UNKNOWN” as CHARSET instead of correct utf-8 in BODYSTRUCTURE response:

C: 11b7e19c9cd84f0f UID FETCH 1 (UID BODYSTRUCTURE)
S: * 1 FETCH (UID 1 BODYSTRUCTURE (“TEXT” “PLAIN” (CHARSET “X-UNKNOWN”) NIL NIL NIL 11894 0 NIL NIL NIL NIL))

Gmail SMTP authentication and STARTTLS bug

$
0
0

Most SMTP servers don’t accept not encrypted connections, or require to secure such connection using explicit SSL.
Usually in such case LOGINDISABLED and STARTTLS are send in response to EHLO command. Some servers send STARTTLS and simply don’t send any AUTH responses.

Recently Gmail started to act differently (and incorrect):

S: 220 mx.google.com ESMTP hc4sm6305585wjc.9 - gsmtp
C: EHLO [192.168.0.11]
S: 250-mx.google.com at your service, [89.67.21.113]
S: 250-SIZE 35882577
S: 250-8BITMIME
S: 250-STARTTLS
S: 250-AUTH LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN
S: 250-ENHANCEDSTATUSCODES
S: 250 CHUNKING
C: AUTH LOGIN
S: 530 5.7.0 Must issue a STARTTLS command first. hc4sm6305585wjc.9 - gsmtp

Server claims that it accepts LOGIN command:
S: 250-AUTH LOGIN
but when it is send, it claims that you must issue STARTTLS first:
S: 530 5.7.0 Must issue a STARTTLS command first. hc4sm6305585wjc.9 - gsmtp

This doesn’t make much sense and Gmail should not send “250-AUTH LOGIN PLAIN”.

NavigateToTest VS2013 extension

$
0
0
Extension is available for other Visual Studio versions:

You can download the extension here:
NavigateToTest Visual Studio 2013 extension

Here’s the latest version that supports Visual Studio 2013.

Extension is convention based. It matches ClassName file with ClassNameTest or ClassNameTests and vice-versa, so you can easily navigate to the test file and back.

Here are some screenshots:

Here’s the toolbar and two opened files:

You can download the extension here:
NavigateToTest Visual Studio 2013 extension

Mail2World IMAP search ALL bug

$
0
0

Another broken IMAP server.


S: * OK Mail2World IMAP4 Server 2.6 64bit ready
S: 76abb5398bc44413 OK CAPABILITY completed
C: 1d5827aea22047ea LOGIN X Y
S: 1d5827aea22047ea OK LOGIN completed
C: b094a8b36bce4d26 EXAMINE "INBOX"
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Recent)
S: * 1 EXISTS
S: * 0 RECENT
S: * OK [PERMANENTFLAGS ()] No permanent flags permitted
S: * OK [UNSEEN 0] first unseen
S: * OK [UIDVALIDITY 42389] UIDs are valid
S: b094a8b36bce4d26 OK [READ-ONLY] opened INBOX
C: 95d4bf743ec949dd UID SEARCH ALL
S: 95d4bf743ec949dd BAD UID SEARCH wrong arguments passed.

“UID SEARCH ALL” is a valid IMAP search query, all servers I know (e.g. Gmail, Exchange) support it without any problems. I can’t imagine a simpler search query, than “UID SEARCH ALL”.

I doubt any email program can download anything from this server.

Funny enough such broken commands as: “UID SEARCH 1:* UID” or “UID SEARCH ALL UID” work on this server.

Nevertheless latest version of Mail.dll is smart enough to access this server.

Eml is now of byte[] type (Cannot implicitly convert type ‘byte[]‘ to ‘string’)

$
0
0

In most recent version of Mail.dll we decided to change how email data is internally stored. This improves both memory usage and raw, not encoded utf-8 data handling. As every major change this leads to a small breaking changes in Mail.dll’s public interface.

In most cases changes required will be very minor. Most common are data type changes from string to byte[] or var keyword.

Below you can find a most common change guidance:

Downloading an email

change:

string eml = client.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(eml);

to:

byte[] eml = client.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(eml);

Saving an email to a file

change:

string eml = client.GetMessageByUID(uid);
File.WriteAllText(fileName, eml, Encoding.GetEncoding(1252));

to:

byte[] eml = client.GetMessageByUID(uid);
File.WriteAllBytes(fileName, eml);

Reading an email from a file

change:

string eml = File.ReadAllText(fileName, Encoding.GetEncoding(1252));
IMail email = new MailBuilder().CreateFromEml(eml);

to:

byte[] eml = File.ReadAllBytes(fileName);
IMail email = new MailBuilder().CreateFromEml(eml);

Uploading an email read from a file

change:

string eml = File.ReadAllText(fileName, Encoding.GetEncoding(1252));
client.UploadMessage("Inbox", eml);

to:

byte[] eml = File.ReadAllBytes(fileName);
client.UploadMessage("Inbox", eml);
Viewing all 120 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>