1

I wrote a simple program written to collect files, send the files, then delete said files. I am sending them via Email using System.Net.Mail

If Label6.Text = "" Then
        mail.Attachments.Add(New Attachment(zipPath))
    End If
    'Enables SSL, if required
    ssl = Provider.ssl
    If skipAhead = True Then
        ssl = True
    End If
    If ssl = True Then
        SmtpServer.EnableSsl = True
    End If
    'Sends the email
    SmtpServer.Send(mail)
    'Allows the user to either keep testing, or quit.
    If skipAhead = True Then
        My.Computer.FileSystem.DeleteFile(unalteredPath)
        My.Computer.FileSystem.DeleteFile(unalteredPath1)
        My.Computer.FileSystem.DeleteFile(zipPath)
    Else
        Dim keepOpen As Integer = MsgBox("The Email was sent. You can keep testing if you would like to. Press ok to close, and cancel to keep testing", MsgBoxStyle.OkCancel)
        If keepOpen = 1 Then
            Close()
        End If
    End If

As seen in line 2, the attachment is added to the email, and I do not attempt to delete the attachment until after the email is sent, however when the code is running, it throws an error that the file is being used by another process.

I am also wondering if this could be lingering from the .zip being created itself. Here is the code that does that:

Public Sub Zipping()
    'Copies files to the folder where they will be zipped from
    My.Computer.FileSystem.CopyFile(unalteredPath, outputs & "\ExIpOutput.txt")
    My.Computer.FileSystem.CopyFile(unalteredPath1, outputs & "\IpConfig.txt")
    'Deletes the old output files
    My.Computer.FileSystem.DeleteFile(unalteredPath)
    My.Computer.FileSystem.DeleteFile(unalteredPath1)
    'Starts the zip Sub
    ZipFile.CreateFromDirectory(outputs, zipPath, CompressionLevel.Fastest, True)
    My.Computer.FileSystem.DeleteDirectory(outputs, FileIO.DeleteDirectoryOption.DeleteAllContents)
End Sub

Here is the CreateFromDirectory sub:

Public Shared Sub CreateFromDirectory(sourceDirectoryName As String, destinationArchiveFileName As String, compressionLevel As Compression.CompressionLevel, includeBaseDirectory As Boolean)
End Sub

Is there something I'm missing here, or do I need to have the program sleep for a bit to let the email send, then delete the .zip file?

David
  • 250
  • 4
  • 15

2 Answers2

3

You can load the file into an array: File.ReadAllBytes(String) Method.

Then get a MemoryStream from that: How do I convert struct System.Byte byte[] to a System.IO.Stream object in C#?

And finally, you can use a MemoryStream for an attachment: Attach a file from MemoryStream to a MailMessage in C#.

As the data to be sent is in memory, you should be able to delete the file. Note that if there is a crash, the data is gone.

The examples are in C#, but if you have problems using the methods in VB.NET, please edit your question to show how far you've got and tell us what the problem is.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • Following your instructions the best I could, I added [this](https://pastebin.com/mgzujtKz) instead of the `attachments.add`, and the program is now throwing [this error](https://pastebin.com/51qHK3Dg) – David Sep 07 '18 at 20:47
  • 1
    As a whole, those weren't instructions: they were the parts that you need to look at and put together with some adjustments ;) N.B. The data in the links you gave does not tell us which line the error occurred on. Use Option Strict On (q.v.) to get Visual Studio to tell you where the problem is. – Andrew Morton Sep 07 '18 at 22:44
  • 3
    A good thing to remember is that both `Attachment` and `MailMessage` implement `IDisposable`. And that `Attachment` holds a `Stream`. – Jimi Sep 08 '18 at 00:50
  • So, I figured out the issue, and wrote a whole new [chunk of code](https://pastebin.com/zg3EhVTX) to deal with converting and attaching the file. Now gmail refuses to send it because of a security issue. That's a different issue, however. This worked. Thank you – David Sep 09 '18 at 03:54
  • @Jimi, you're on the money there. It's the `Attachment` that locks the file and disposing the `Attachment` will release the file, so making any changes besides that is unnecessary. – jmcilhinney Sep 09 '18 at 04:13
  • @jmcilhinney Yes, that was the meaning of that comment :) @David If you still have some problems with `gmail` security, open your Google account settings then, in `Sign-in & security`, enable `Allow less secure apps`. You, of course, also need `EnableSsl = True` and valid `NetworkCredentials` on the SMTP client. – Jimi Sep 09 '18 at 06:26
  • 1
    @Jimi turns out the attachment.dipose() was the problem. I had the gmail settings configured correctly. The error thrown was just odd. – David Sep 09 '18 at 20:06
2

A better solution to this issue is to dispose the Attachment object that is locking the file. Any object you create that has a Dispose method should have that method called when you're done with the object and an Attachment is no different.

Dim fileAttachment As Attachment

If Label6.Text = "" Then
    fileAttachment = New Attachment(zipPath)
    mail.Attachments.Add(fileAttachment)
End If

'...

SmtpServer.Send(mail)

If fileAttachment IsNot Nothing Then
    fileAttachment.Dispose()
End If
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46