Programm greift auf Datei zu, nachdem sie als Mailanhang versendet wurde

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    Programm greift auf Datei zu, nachdem sie als Mailanhang versendet wurde

    Holla
    Ich habe eine kleine Funktion, mit der ich Einträge aus meinem Adressbuch eine Email senden kann.
    Mein Problem ist, dass ich eine Datei, die ich als Anhang versendet habe, nicht löschen kann, bis ich mein Programm beende, da dieses auf die Datei zugreift. Auch nachdem die Mail lange weg ist.

    VB.NET-Quellcode

    1. Private Sub BTNSendMail_Click(sender As Object, e As EventArgs) Handles BTNSendMail.Click
    2. Using sendmail As New frmSendMail
    3. sendmail.DtsSettings = Me.DtsSettings
    4. sendmail.MailSettingsBindingSource.DataSource = Me.DtsSettings
    5. 'Prüfen ob Zeile im Adressbuch ausgewählt
    6. If Not PersonBindingSource.Current Is Nothing Then
    7. Dim Address = DirectCast(DirectCast(PersonBindingSource.Current, DataRowView).Row, DtsSettings.PersonRow)
    8. 'Emailadresse des selektierten Eintrages auslesen, wenn Email vergeben, Übergabe an sendmail
    9. If Address.Mail1 <> "" Then
    10. Dim Recipient As String = Address.Mail1
    11. sendmail.TBRecipient.Text = Recipient
    12. End If
    13. End If
    14. sendmail.ShowDialog()
    15. End Using
    16. End Sub

    Der Anhang wird dann erst in der frmSendMail eingefügt.

    Aber nach meinem Verständnis muss doch, durch den Using Block, die erzeugte Instanz sendmail nach Ablauf der Sub zerstört werden.
    Warum greift mein Programm dann noch auf den Anhang zu?
    Der Code zeigt leider nicht den Mailversand. Daher ist auch nicht auszumachen, wo Du ggf. ein Dispose/Using-Block vergessen hast. Hier geht es ja nur um ein Form. Und das ist sicherlich nicht das Problem.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Bitte entschuldige. Für mich war folgendes klar:

    VB.NET-Quellcode

    1. Using form as new formname
    2. 'alles - wirklich alles innerhalb des Using Blocks ist "weg", wenn das Ende des Using Blocks erreicht wird.
    3. End Using

    Deswegen war ich ja so verwundert, dass ich keinen Zugriff auf die Datei (den Mailanhang) habe.
    Aber scheinbar, hab ich ja was falsch verstanden :o)

    Hier der relevante Code aus frmSendMail
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class frmSendMail
    2. Dim Attachments As New List(Of String)
    3. 'Anhang anhängen
    4. 'Button zum hinzufügen eines Anhangs
    5. Private Sub BTNAddAttachment_Click(sender As Object, e As EventArgs) Handles BTNAddAttachment.Click
    6. 'Open File Dialog anzeigen
    7. OFDAttachment.Filter = "Alle Dateien (*.*)|*.*"
    8. OFDAttachment.FilterIndex = 1
    9. If OFDAttachment.ShowDialog() = Windows.Forms.DialogResult.OK Then
    10. 'abbrechen, wenn Datei bereits ausgewählt
    11. For Each item In Attachments
    12. If item = OFDAttachment.FileName Then Exit Sub
    13. Next
    14. 'Dateipfad in List of String speichern
    15. Attachments.Add(OFDAttachment.FileName)
    16. 'den letzten Eintrag (oben hinzugefügt) in ListofString in LVAttachment anzeigen
    17. LVAttachment.Items.Add(Path.GetFileName(Attachments(Attachments.Count - 1)))
    18. End If
    19. End Sub
    20. 'und die Subs zum Mailversand
    21. Private Sub BTNSendMail_Click(sender As Object, e As EventArgs) Handles BTNSendMail.Click
    22. getMailInfo()
    23. End Sub
    24. Private Sub getMailInfo()
    25. 'Prüfen ob SMTP Daten hinterlegt
    26. If MailSettingsBindingSource.Current Is Nothing Then
    27. MessageBox.Show("Mail kann nicht versendet werden " & Environment.NewLine & " Es wurden keine SMTP Daten gefunden")
    28. Exit Sub
    29. End If
    30. Dim MailSettings = DirectCast(DirectCast(MailSettingsBindingSource.Current, DataRowView).Row, DtsSettings.MailSettingRow)
    31. 'Emaileinstellungen aus der Binding Source holen
    32. Dim MailSender As String = MailSettings.MailAddress
    33. 'Wenn Inhalt aus CMBSender <> Mailadresse aus Binding Source ist, wurde eine Mail ausgewählt und CMBSender verändert
    34. 'dann abbruch
    35. If MailSender <> CMBSender.Text Then
    36. MessageBox.Show("ungültige Emailadresse")
    37. Exit Sub
    38. End If
    39. 'resliche Daten laden und Sub Sendmail zum versenden der Mail aufrufen
    40. Dim Password As String = MailSettings.Password
    41. Dim Port As Integer = MailSettings.Port
    42. Dim SMTPServer As String = MailSettings.SMTPServer
    43. Dim SSL As Boolean = MailSettings.SSL
    44. SendMail(MailSender, Password, Port, SMTPServer, SSL, TBRecipient.Text, TBBCC.Text, TBCC.Text, TBSubject.Text, TBMessage.Text, TBSignature.Text)
    45. End Sub
    46. 'Sub zum senden einer Mail
    47. Private Sub SendMail(Sender As String, Password As String, Port As Integer, SMTPServer As String, SSL As Boolean, Recipient As String, bcc As String, cc As String, Subject As String, Message As String, Signature As String)
    48. Dim Token As New Object
    49. 'Prüfen ob Empfängeradresse korrekt ist
    50. If Recipient = "" Or (Not (Recipient.Contains("@"))) Or (Not (Recipient.Contains("."))) Then
    51. MessageBox.Show("ungültige Empfängeradresse")
    52. Exit Sub
    53. End If
    54. 'Prüfen ob bcc korrekt ist, wenn <> ""
    55. If bcc <> "" Then
    56. If (Not (bcc.Contains("@"))) Or (Not (bcc.Contains("."))) Then
    57. MessageBox.Show("ungültige bcc Adresse")
    58. Exit Sub
    59. End If
    60. End If
    61. 'Prüfen ob cc korrekt ist, wenn <> ""
    62. If cc <> "" Then
    63. If (Not (cc.Contains("@"))) Or (Not (cc.Contains("."))) Then
    64. MessageBox.Show("ungültige cc Adresse")
    65. Exit Sub
    66. End If
    67. End If
    68. 'Prüfen ob Betreff belegt ist, wenn nicht Frage ob trotzdem versenden
    69. If Subject = "" Then
    70. If MessageBox.Show("Es wurde kein Betreff eingegeben." & Environment.NewLine & "Möchten Sie die Mail trotzdem versenden?", "kein Betreff", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then
    71. Exit Sub
    72. End If
    73. End If
    74. 'Prüfen ob Nachricht belegt ist, wenn nicht Frage ob trotzdem versenden
    75. If Message = "" Then
    76. If MessageBox.Show("Es wurde keine Nachricht eingegeben." & Environment.NewLine & "Möchten Sie die Mail trotzdem versenden?", "keine Nachricht", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then
    77. Exit Sub
    78. End If
    79. End If
    80. 'Prüfen ob Signatur beleget ist, wenn ja hinter Nachricht einfügen
    81. If Signature <> "" Then Message &= Environment.NewLine & Environment.NewLine & Signature
    82. 'Progressbar sichtbar machen und Emailsende Label beschreiben
    83. PBSendMail.Visible = True
    84. LBLSendMail.Text = "email wird versendet"
    85. 'Mailnachricht erzeugen
    86. Dim Mail As New MailMessage
    87. Dim myCredentials As New System.Net.NetworkCredential
    88. myCredentials.UserName = Sender
    89. myCredentials.Password = Password
    90. Mail.IsBodyHtml = False
    91. 'SMTP Server erzeugen
    92. Dim SMTP As New SmtpClient()
    93. 'Email gesendet Event erstellen
    94. AddHandler SMTP.SendCompleted, AddressOf sendMail_SendCompleted
    95. With SMTP
    96. .EnableSsl = SSL
    97. .Host = SMTPServer
    98. .Port = Port
    99. .UseDefaultCredentials = False
    100. .Credentials = myCredentials
    101. End With
    102. Try
    103. With Mail
    104. .From = New MailAddress(Sender)
    105. .To.Add(Recipient)
    106. If bcc <> "" Then .Bcc.Add(bcc)
    107. If cc <> "" Then .CC.Add(cc)
    108. .Subject = Subject
    109. .Body = Message
    110. If Attachments.Count > 0 Then
    111. For i = 0 To Attachments.Count - 1
    112. .Attachments.Add(New System.Net.Mail.Attachment(Attachments(i)))
    113. Next
    114. End If
    115. End With
    116. 'Email Asynchron versenden
    117. SMTP.SendAsync(Mail, Token)
    118. Catch ex As Exception
    119. 'Progressbar verstecken und Emailsende Label leeren
    120. PBSendMail.Visible = False
    121. LBLSendMail.Text = ""
    122. MessageBox.Show(ex.Message & ex.StackTrace.ToString)
    123. End Try
    124. End Sub
    125. Private Sub sendMail_SendCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    126. Me.Close()
    127. End Sub
    128. End Class


    Ich habe bereits rausgefunden, dass die List(of String) namens Attachment nicht die Ursache ist.
    Ich kann einen Anhang auswählen, und diesen dann löschen (wenn ich eben die Mail nicht abschicke).
    Also bleibt ja eigentlich nur das "Token" aus der Sub Sendmail.
    Daher habe ich testweise dieses Modulweit Private deklariert (Private Token as new object)
    und dann in der sendmail_sendcompleted Sub ein
    Token = nothing ausgeführt, allerdings auch ohne Erfolg
    Nirgends :o)
    Wenn ich das richtig verstanden habe (hab viel von der Mail Sub kopiert), dann muss ich in der sendMail_sendcompleted Sub disposen.
    Denn diese wird gestartet, wenn die Mail fertig versendet ist.
    Ich habe also ​Dim Mail As New MailMessage Modulweit gültig gemacht (Private Mail As New MailMessage) unter Public Class...
    In der SendMail_SendCompleted Sub rufe ich dann ​Mail = Nothing auf.
    Allerdings bringt das nicht den gewünschten Erfolg.
    Hab ich was falsch verstanden / gemacht?
    Weiß nicht was Du falsch machst, ich benutze das nicht, da ich Outlook fernsteuere habe ich dieses Problem nicht.
    Ich finde beim Googlen deines Problems aber deutlich diese Hinweise.

    Auch interessant für dich: docs.microsoft.com/de-de/dotne….mailmessage?view=net-5.0
    Sieht ein bischen anders aus, da wird aber das Attachment disposed, hier sehr verkürzt:

    C#-Quellcode

    1. MailMessage message = new MailMessage(...);
    2. Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
    3. message.Attachments.Add(data);
    4. data.Dispose();
    hmm.
    Ich weiß nicht, ob ichs richtig umgesetzt habe.
    Mit meiner Sub kann ich Emails ohne Anhang versenden. Emails mit Anhang kommen nicht an (Marko läuft im Einzelschritt problemlos durch).
    Ich kann jedoch die Datei löschen.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub SendMail(Sender As String, Password As String, Port As Integer, SMTPServer As String, SSL As Boolean, Recipient As String, bcc As String, cc As String, Subject As String, Message As String, Signature As String)
    2. Dim Token As New Object
    3. Dim Mail As New MailMessage
    4. Dim data As Attachment
    5. 'Prüfen ob Empfängeradresse korrekt ist
    6. If Recipient = "" Or (Not (Recipient.Contains("@"))) Or (Not (Recipient.Contains("."))) Then
    7. MessageBox.Show("ungültige Empfängeradresse")
    8. Exit Sub
    9. End If
    10. 'Prüfen ob bcc korrekt ist, wenn <> ""
    11. If bcc <> "" Then
    12. If (Not (bcc.Contains("@"))) Or (Not (bcc.Contains("."))) Then
    13. MessageBox.Show("ungültige bcc Adresse")
    14. Exit Sub
    15. End If
    16. End If
    17. 'Prüfen ob cc korrekt ist, wenn <> ""
    18. If cc <> "" Then
    19. If (Not (cc.Contains("@"))) Or (Not (cc.Contains("."))) Then
    20. MessageBox.Show("ungültige cc Adresse")
    21. Exit Sub
    22. End If
    23. End If
    24. 'Prüfen ob Betreff belegt ist, wenn nicht Frage ob trotzdem versenden
    25. If Subject = "" Then
    26. If MessageBox.Show("Es wurde kein Betreff eingegeben." & Environment.NewLine & "Möchten Sie die Mail trotzdem versenden?", "kein Betreff", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then
    27. Exit Sub
    28. End If
    29. End If
    30. 'Prüfen ob Nachricht belegt ist, wenn nicht Frage ob trotzdem versenden
    31. If Message = "" Then
    32. If MessageBox.Show("Es wurde keine Nachricht eingegeben." & Environment.NewLine & "Möchten Sie die Mail trotzdem versenden?", "keine Nachricht", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then
    33. Exit Sub
    34. End If
    35. End If
    36. 'Prüfen ob Signatur beleget ist, wenn ja hinter Nachricht einfügen
    37. If Signature <> "" Then Message &= Environment.NewLine & Environment.NewLine & Signature
    38. 'Progressbar sichtbar machen und Emailsende Label beschreiben
    39. PBSendMail.Visible = True
    40. LBLSendMail.Text = "email wird versendet"
    41. 'Mailnachricht erzeugen
    42. Dim myCredentials As New System.Net.NetworkCredential
    43. myCredentials.UserName = Sender
    44. myCredentials.Password = Password
    45. Mail.IsBodyHtml = False
    46. 'SMTP Server erzeugen
    47. Dim SMTP As New SmtpClient()
    48. 'Email gesendet Event erstellen
    49. AddHandler SMTP.SendCompleted, AddressOf sendMail_SendCompleted
    50. With SMTP
    51. .EnableSsl = SSL
    52. .Host = SMTPServer
    53. .Port = Port
    54. .UseDefaultCredentials = False
    55. .Credentials = myCredentials
    56. End With
    57. Try
    58. With Mail
    59. .From = New MailAddress(Sender)
    60. .To.Add(Recipient)
    61. If bcc <> "" Then .Bcc.Add(bcc)
    62. If cc <> "" Then .CC.Add(cc)
    63. .Subject = Subject
    64. .Body = Message
    65. If Attachments.Count > 0 Then
    66. For i = 0 To Attachments.Count - 1
    67. data = New Attachment(Attachments(i), MediaTypeNames.Application.Octet)
    68. Mail.Attachments.Add(data)
    69. data.Dispose()
    70. Next
    71. End If
    72. End With
    73. 'Email Asynchron versenden
    74. SMTP.SendAsync(Mail, Token)
    75. Catch ex As Exception
    76. 'Progressbar verstecken und Emailsende Label leeren
    77. PBSendMail.Visible = False
    78. LBLSendMail.Text = ""
    79. MessageBox.Show(ex.Message & ex.StackTrace.ToString)
    80. End Try
    81. End Sub


    Edit: Meine Gedanken dazu sind folgende:
    Die mail kommt nicht an, weil ich dispose, bevor die Mail fertig versendet ist.
    Da ich das ganze asynchron versende, wird eben dispose aufgerufen, bevor die Mail durch ist.
    Ich muss also in der ​sendMail_SendCompleted Sub disposen, weil diese erreicht wird, nachdem die Mail fertig versendet ist.
    Das habe ich auf meine Version angewendet (Sub SendMail aus Post3):
    Zeile87: ​Dim Mail As New MailMessage habe ich modulweit gültig gemacht. Also Private Mail As New MailMessage
    und dann folgende sendMail_SendCompleted Sub:

    VB.NET-Quellcode

    1. Private Sub sendMail_SendCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    2. Mail.Dispose()
    3. Me.Close()
    4. End Sub

    Es scheint alles zu funktionieren.

    Macht das Sinn was ich hier getan hab?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerSmurf“ ()

    Soweit ich sehen kann: ja. Allerdings solltest Du zur Vollständigkeit noch den Handler wieder deabonnieren.

    VB.NET-Quellcode

    1. Private Sub sendMail_SendCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    2. Mail.Dispose()
    3. Me.Close()
    4. RemoveHandler SMTP.SendCompleted, AddressOf sendMail_SendCompleted
    5. End Sub


    Warum eigentlich asynchron/nebenläufig? Kann der Versand so lange dauern?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ok, baue ich noch ein.
    Ich Frage mich, ob ich "Mail" auch an dem Händler übergeben kann. (edit: Sorry! Handy autokorrektur...)
    Das wäre ja wahrscheinlich eleganter, als sie modulweit gültig zu haben.
    Also nach dem Prinzip (sendcompleted(Mail))

    Ich glaube ich hab's asynchron gemacht, weil ich unbedingt so eine (fragliche) Progressbar haben wollte.
    Und in der "normalen" Variante kommt es so vor, als wenn das Programm einfriert.
    Zwar sind die üblichen Anhänge recht klein, aber bei unserem Provinznetz dauern auch 3mb ein bisschen :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerSmurf“ ()