High memory usage while sending/receiving messages usign smtp/imap client

During the sending or receiving of messages (.eml), the memory usage is very high.
For example, for a 100MB file, the memory used by the process reaches 1.6GB.

     public async Task SendMailWithLargeAttachTest()
        {
            /* Path to Aspose License */
            const string ASPOSE_LIC_PATH = "ASPOSE_LIC_PATH";

            /* SMTP client configuration */
            const string host = "localhost";
            const int port = 465;
            const string username = "username";
            const string password = "password";

            /* test mail data */
            const string from = "addressFrom";
            const string to = "toAddress";

            /* temporary path */
            const string tmpPath = "tmpPath";

            new License().SetLicense(ASPOSE_LIC_PATH);


            string attachPath = Path.Combine(tmpPath, "file100M.txt");
            try
            {


                using (var msg = new MailMessage(from, to)
                {
                    Subject = "Test File100M"

                })
                {
                    using (var fs = new FileStream(attachPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
                    {
                        fs.SetLength(100 * 1024 * 1024);
                        await fs.FlushAsync();
                        fs.Position = 0;
                        msg.AddAttachment(new Attachment(fs, Path.GetFileName(attachPath)));

                        using (var smtpClient = new Aspose.Email.Clients.Smtp.SmtpClient(host, port, username, password))
                        {

                            smtpClient.SucceededSending += (sender, eventArgs) => Console.WriteLine(eventArgs.Message);
                            smtpClient.FailedSending += (sender, eventArgs) => Console.WriteLine(eventArgs.OperationError.Message, eventArgs.OperationError.StackTrace);
                            await smtpClient.SendAsync(msg);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

Hello @lamfab,

Thank for writing to Aspose.Email support forum.

Which version of Aspose.Email do you use?

I am using Aspose.Email version 23.3.0.
I have also tried the latest version, 23.4.0, but I am still experiencing the same issue.
The attached pictures show the memory usage during a test with version 23.4.0.
JustBeforeSending.png (103.0 KB)
SendingToSmtp.png (107.1 KB)

@lamfab
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): EMAILNET-41061

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

I forgot to mention that in an x86 application, this led to an out-of-memory exception.

Hello @lamfab,

This additional information has been added to the ticket.

Thanks.

Hello @lamfab,

We tried to reduce the amount of memory in the new Aspose.Email 23.5 version.

It’s worth noting that:

  • Logging requires a lot of memory. It can be disabled in the following way:
  client.EnableLogger = false;
  • TransferEncoding requires a lot of memory to convert to Base64. Use the following code to check:
  Attachment a = new Attachment(fs, Path.GetFileName(attachPath));
  a.TransferEncoding = Aspose.Email.Mime.TransferEncoding.Unknown;

Also, please, note that the email infrastructure isn’t intended to transmit large messages. Limitations are typically imposed by email service providers to ensure efficient handling and delivery of emails.

For example, Gmail, currently has a maximum limit of 25 megabytes (MB) for the total size of an incoming or outgoing message, including attachments. This includes both the message body and any attached files. Other providers may have different size limits in place.

If you need to send a large file, you may want to consider alternative methods such as reference attachments, and provide a link to the recipient instead of attaching the files directly to the email.

Thanks for your patience.

Hello,
I have tried with the latest version of Aspose.Email: 24.5.0 and the problem still persists.

With a 34MiB email file (in binary) that is 25MiB encoded in Base64, a whopping 270 MB of RAM is used just to upload the file in an IMAP folder.

I have tried to upload the email, zipped, which is 12MiB but the forum gives this funny error: Sorry, that file is too big (maximum size is 48.8 MB)

This is the code, at the last line “AppendMessage” is the single operation that is allocating so much RAM, here MIME_MESSAGE_25MB is the file path of the MIME message saved on disk.

using (var client2 = new Aspose.Email.Clients.Imap.ImapClient(HOST, PORT))
{
	client2.SecurityOptions = Aspose.Email.Clients.SecurityOptions.None;
	client2.Username = USR; client2.Password = PWD;
	client2.SelectFolder("InBox");
	client2.AppendMessage("InBox", MIME_MESSAGE_25MB); // << THIS ALLOCATES
}

We are seeing like a 10x allocation size for what should only be a socket data transfer with no additional processing required.
It would be ok even with a 2x allocation but this is clearly some useless data cloning happening.

Just as a quick comparison, doing the same thing with MailBee.NET (by Afterlogic) there is literally ZERO memory allocation because the file is clearly streamed directly to the server as it should be in the best case scenario.

var message = new MailBee.Mime.MailMessage();
message.LoadMessage(MIME_MESSAGE_25MB);
using (var client = new MailBee.ImapMail.Imap())
{
	client.Connect(HOST, PORT);
	client.Login(USR, PWD);
	client.SelectFolder("InBox");
	client.UploadMessage(message, "InBox");
}

If the library was allocating 2 or 3 times the email size in memory it would still be wrong but at least more acceptable that 10 times.
This much allocation is always dangerous, even if there is enough free RAM, we could still incur in an OutOfMemoryException because these are CONTIGUOUS BLOCKS allocations so, memory could be fragmented and Windows could not have hundred of megabytes of contiguous free memory to allocate.
See OutOfMemoryException Class (System) | Microsoft Learn

What kind of processing would justify so much memory allocation? I think this qualifies a bug because it is not expected behaviour that wastes hardware and causes instability.

Thanks.

@lamfab
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): EMAILNET-41357

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.