Skip to content

File used in attachment is being locked after send #269

Open

Description

@Gaz83

I have a program listening to messages from a Message Broker (Rabbit MQ) and when a message comes in it sends an email.
In the message I have a property with attachment path, which is an ftp site.
I check if this is valid and download the attachment. Once downloaded I attach to the email and send.

What I am noticing is that if I send the email, move on to the next message and try to repeat the above with the SAME attachment, I get the following error
System.IO.IOException: The process cannot access the file 'C:\Temp\Somepic.jpg' because it is being used by another process.

This happens at the point when I try to delete the attachment file.

I am using the MailKit as the sender.

A bit of code to help

            public async Task Consume(ConsumeContext<EmailMessage> context)
	{
		await Task.Delay(5000); // Put this in case there needs to be a delay form the last email send to allow release of file.

		_logger.LogInformation("Email recieved");

		var message = context.Message;

		var _email = _emailFactory.Create(); // _emailFactory is injected into the class. I had IFluentEmail injected before, but tried this for a fresh email each time.

		_email.BCC(message.BccAddresses)
			.CC(message.CcAddresses)
			.To(message.ToAddresses)
			.Body(message.Body, message.IsHtml);

		if (message.HasAttachment)
		{
			GetAttachment(message, _email); // Exception happens in here when it tries to delete the file from the previous send.
		}

		_logger.LogInformation("Sending Email.");

		try
		{
			var response = await _email.SendAsync();

			if (response.Successful)
			{
				_logger.LogInformation("Sent");
			}
			else
			{
				foreach (var responseErrorMessage in response.ErrorMessages)
				{
					_logger.LogInformation(responseErrorMessage);
				}
			}
		}
		catch (Exception e)
		{
			_logger.LogError(e, "Error Sending email");
		}
	}

            private bool GetAttachment(EmailMessage message, IFluentEmail _email)
	{
		if (!string.IsNullOrEmpty(message.AttachmentPath))
		{
			_logger.LogInformation("Getting attachment");

			var pathSplit = message.AttachmentPath.Split(';');

			using var ftp = new FtpConnection(_logger, pathSplit[0], pathSplit[1], pathSplit[2]);

			if (ftp.OpenConnection())
			{
				var tempPath = @"D:\Temp\Services\Email";
				var fileName = Path.GetFileName(pathSplit[3]);
				var fullPath = Path.Combine(tempPath, fileName);

				if (File.Exists(fullPath))
				{
					_logger.LogInformation("File exists in temp folder so deleting.");

					try
					{
						File.Delete(fullPath); // IO Exception happens here
					}
					catch (Exception e)
					{
						Console.WriteLine(e);
					}
				}

				_logger.LogInformation($"Downloading File {pathSplit[3]}.");

				ftp.DownloadFile(pathSplit[3], fullPath);

				if (File.Exists(fullPath))
				{
					_email.AttachFromFilename(fullPath, GetContentTypeFromFileName(fullPath));
				}
				else
				{
					_logger.LogError("Email could not be sent, file attachment did not download.");
					return false;
				}
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}

		return true;
	}

Activity

  1. CoderBrad commented on Dec 21, 2021

    @CoderBrad

    It looks like the issue is that AttachFromFilename opens a read stream which is never closed. I experienced the same issue with MailGun (which would make sense since the issue is in Core). My workaround is to call:
    email.Data.Attachments.ForEach(async f => await f.Data.DisposeAsync());
    after SendAsync to close attachment streams so I can then do what I want with the files. Not optimal but I don't know what to suggest as a better option since I'm not sure how those streams are used throughout the library. My solution may even cause issues somewhere else but it seems to be working for me for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions