Imports System.ComponentModel
Imports System.IO
Imports System.Text
Imports ComponentPro.Net.Mail

Namespace MimeSamples
	Partial Public Class MimeComposer
		Inherits Form
		Private ReadOnly _exception As Boolean
		Private _changed As Boolean
		Private _mailFileName As String
		Private _attachments As AttachmentCollection
		Private _internalChanges As Boolean

		Public Sub New()
			Try
				InitializeComponent()
			Catch exc As ComponentPro.Licensing.Mail.UltimateLicenseException
				MessageBox.Show(exc.Message, "Error")
				_exception = True
				Return
			End Try

			' Attachs the TextChanged event handler to all text boxes.
			AddHandler txtBcc.TextChanged, AddressOf txt_TextChanged
			AddHandler txtBody.TextChanged, AddressOf txt_TextChanged
			AddHandler txtCc.TextChanged, AddressOf txt_TextChanged
			AddHandler txtFrom.TextChanged, AddressOf txt_TextChanged
			AddHandler txtSubject.TextChanged, AddressOf txt_TextChanged
			AddHandler txtTo.TextChanged, AddressOf txt_TextChanged

			' New messages.
			NewMesssage()
		End Sub

		Protected Overrides Sub OnLoad(ByVal e As EventArgs)
			MyBase.OnLoad(e)
			If _exception Then
				Me.Close()
			End If
		End Sub

		Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)
			If AskSaving() Then
				e.Cancel = True
			End If

			MyBase.OnClosing(e)
		End Sub

		Private Sub txt_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
			' Changes the form's title if needed.
			Dim b As Boolean = _changed
			_changed = True
			saveButton.Enabled = True
			If b = False Then
				SetTitle()
			End If
		End Sub

		Private Sub SetTitle()
			If Not _internalChanges Then
				' Sets form's title.
				Dim str As String = "Ultimate Mime Composer"

				If _mailFileName IsNot Nothing Then
					str &= " - " & Path.GetFileName(_mailFileName)
				End If

				If txtSubject.Text.Length > 0 Then
					str &= " - " & txtSubject.Text
				End If

				If _changed Then
					str &= "*"
				End If

				Me.Text = str
			End If
		End Sub

		Private Sub txtSubject_TextChanged(ByVal sender As Object, ByVal e As EventArgs) Handles txtSubject.TextChanged
			' Changes the form's title whenever the subject is changed.
			SetTitle()
		End Sub

		''' <summary>
		''' Creates new message.
		''' </summary>
		Private Sub NewMesssage()
			_internalChanges = True
			txtBcc.Text = String.Empty
			txtBody.Text = String.Empty
			txtCc.Text = String.Empty
			txtFrom.Text = String.Empty
			txtSubject.Text = String.Empty
			txtTo.Text = String.Empty
			cbxAttachment.Items.Clear()
			_mailFileName = Nothing
			_attachments = Nothing
			_changed = False
			_internalChanges = False
			SetTitle()
			saveAttachmentsButton.Enabled = False
			saveButton.Enabled = False
		End Sub

		''' <summary>
		''' Opens an existing message.
		''' </summary>
		''' <param name="fileName"></param>
		Private Sub OpenMessage(ByVal fileName As String)
			_internalChanges = True
			Dim message As New MailMessage()
			_mailFileName = fileName
			message.Load(fileName)

			txtSubject.Text = message.Subject
			txtBody.Text = message.BodyText.Replace(vbLf, vbCrLf)

			Dim sb As New StringBuilder()

			For Each [to] As MailAddress In message.To
				Dim address As String = [to].ToString()
				If address.Length > 0 Then
					sb.Append(address)
					sb.Append(";"c)
				End If
			Next [to]
			If sb.Length > 0 Then
				sb.Length -= 1
			End If
			txtTo.Text = sb.ToString()

			sb.Length = 0
			For Each bcc As MailAddress In message.Bcc
				Dim address As String = bcc.ToString()
				If address.Length > 0 Then
					sb.Append(address)
					sb.Append(";"c)
				End If
			Next bcc
			If sb.Length > 0 Then
				sb.Length -= 1
			End If
			txtBcc.Text = sb.ToString()

			sb.Length = 0
			For Each cc As MailAddress In message.Cc
				Dim address As String = cc.ToString()
				If address.Length > 0 Then
					sb.Append(address)
					sb.Append(";"c)
				End If
			Next cc
			If sb.Length > 0 Then
				sb.Length -= 1
			End If
			txtCc.Text = sb.ToString()

			sb.Length = 0
			For Each [from] As MailAddress In message.From
				Dim address As String = [from].ToString()
				If address.Length > 0 Then
					sb.Append(address)
					sb.Append(";"c)
				End If
			Next [from]
			If sb.Length > 0 Then
				sb.Length -= 1
			End If
			txtFrom.Text = sb.ToString()

			If message.Attachments.Count > 0 Then
				_attachments = New AttachmentCollection()
				For Each att As Attachment In message.Attachments
					_attachments.Add(att)
					cbxAttachment.Items.Add(Path.GetFileName(att.FileName))
				Next att
				cbxAttachment.SelectedIndex = 0
				btnRemoveAttachment.Enabled = True
				saveAttachmentsButton.Enabled = True
			Else
				saveAttachmentsButton.Enabled = False
			End If
			_changed = False
			saveButton.Enabled = False
			_internalChanges = False
		End Sub

		''' <summary>
		''' Shows Save as dialog and save the message to the specified file.
		''' </summary>
		Private Sub SaveMessageAs()
			Dim dlg As New SaveFileDialog()
			Try
				dlg.OverwritePrompt = True
				dlg.Filter = "Email files (*.eml)|*.eml|All files (*.*)|*.*"
				dlg.FilterIndex = 1
				dlg.Title = "Save e-mail message as"
				If dlg.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
					Return
				End If

				_mailFileName = dlg.FileName
				SaveMessageAs(dlg.FileName)
			Catch
				MessageBox.Show(dlg.FileName & " is not an email file", "Error")
			End Try
		End Sub

		''' <summary>
		''' Creates a new Message object.
		''' </summary>
		''' <returns>A new Message object.</returns>
		Private Function CreateMessage() As MailMessage
			Dim message As New MailMessage()

			message.Subject = txtSubject.Text
			message.BodyText = txtBody.Text

			For Each [to] As String In txtTo.Text.Split(New Char() {";"c, ","c})
				Dim email As String = [to].Trim()
				If email.Length > 0 Then
					message.To.Add(email)
				End If
			Next [to]

			For Each bcc As String In txtBcc.Text.Split(New Char() { ";"c, ","c })
				Dim email As String = bcc.Trim()
				If email.Length > 0 Then
					message.Bcc.Add(email)
				End If
			Next bcc

			For Each cc As String In txtCc.Text.Split(New Char() { ";"c, ","c })
				Dim email As String = cc.Trim()
				If email.Length > 0 Then
					message.Cc.Add(email)
				End If
			Next cc

			For Each [from] As String In txtFrom.Text.Split(New Char() { ";"c, ","c })
				Dim email As String = [from].Trim()
				If email.Length > 0 Then
					message.From.Add(email)
				End If
			Next [from]

			If _attachments IsNot Nothing Then
				For Each att As Attachment In _attachments
					message.Attachments.Add(att)
				Next att
			End If

			Return message
		End Function

		''' <summary>
		''' Saves the current message as a file.
		''' </summary>
		''' <param name="fileName"></param>
		Private Sub SaveMessageAs(ByVal fileName As String)
			Dim message As MailMessage = CreateMessage()
			message.Save(fileName)
			_changed = False
			saveButton.Enabled = False
			SetTitle()
		End Sub

		Private Sub SaveMessage()
			If _mailFileName Is Nothing Then
				SaveMessageAs()
			Else
				Try
					SaveMessageAs(_mailFileName)
				Catch exc As Exception
					MessageBox.Show(String.Format("Unable to save the message to file: '{0}'" & vbCrLf & "{1}", _mailFileName, exc.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop)
				End Try
			End If
		End Sub

		''' <summary>
		''' Saves attachments to a specific folder.
		''' </summary>
		Private Sub SaveAttachmentAs(ByVal folder As String)
			For Each att As Attachment In _attachments
				att.Save(Path.Combine(folder, att.FileName))
			Next att
		End Sub

		''' <summary>
		''' Saves attachments to a specific folder. A browing folder dialog will be shown.
		''' </summary>
		Private Sub SaveAttachmentAs()
			Dim folderBrowserDialog As New FolderBrowserDialog()
			If folderBrowserDialog.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
				Return
			End If

			Dim path As String = folderBrowserDialog.SelectedPath
			SaveAttachmentAs(path)
		End Sub

		''' <summary>
		''' If the message has not been saved, shows a message box asking user to save the changes.
		''' </summary>
		''' <returns>A bool value indicating whether the closing action should be cancelled.</returns>
		Private Function AskSaving() As Boolean
			If _changed Then
				Dim result As DialogResult = MessageBox.Show("Do you want to save the changes you have made?", "Mime Composer", MessageBoxButtons.YesNoCancel)
				If result = System.Windows.Forms.DialogResult.Cancel Then
					Return True
				End If
				If result = System.Windows.Forms.DialogResult.Yes Then
					SaveMessage()
				End If
			End If

			Return False
		End Function

		Private Sub newMessageButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles newMessageButton.Click
			If Not AskSaving() Then
				NewMesssage()
			End If
		End Sub

		Private Sub openMessageButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles openMessageButton.Click
			If Not AskSaving() Then
				Dim dlg As New OpenFileDialog()
				Try
					dlg.Filter = "Email files (*.eml)|*.eml|Outlook files (*.msg)|*.msg|All files (*.*)|*.*"
					dlg.FilterIndex = 1
					dlg.Title = "Select an email file"
					If dlg.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
						Return
					End If

					OpenMessage(dlg.FileName)
					SetTitle()
				Catch
					MessageBox.Show(dlg.FileName & " is not an email file", "Error")
				End Try
			End If
		End Sub

		Private Sub saveButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveButton.Click
			If _changed Then
				SaveMessage()
			End If
		End Sub

		Private Sub saveAsButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveAsButton.Click
			SaveMessageAs()
		End Sub

		Private Sub saveAttachmentsButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveAttachmentsButton.Click
			SaveAttachmentAs()
		End Sub

		Private Sub exitButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles exitButton.Click
			Me.Close()
		End Sub

		Private Sub cutButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cutButton.Click
			txtBody.Cut()
		End Sub

		Private Sub copyButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles copyButton.Click
			txtBody.Copy()
		End Sub

		Private Sub pasteButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles pasteButton.Click
			txtBody.Paste()
		End Sub

		Private Sub selectAllButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles selectAllButton.Click
			txtBody.SelectAll()
		End Sub

		Private Sub btnAddAttachment_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAddAttachment.Click
			Dim dlg As New OpenFileDialog()
			Try
				Dim b As Boolean = _changed

				dlg.Filter = "All files (*.*)|*.*"
				dlg.FilterIndex = 1
				dlg.Title = "Select a file"
				dlg.Multiselect = True
				If dlg.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
					Return
				End If

				' Creates an AttachmentCollection if _attachments is null.
				If _attachments Is Nothing Then
					_attachments = New AttachmentCollection()
				End If

				' Adds selected files to the attachment collection and the combo box as well.
				For Each fileName As String In dlg.FileNames
					_attachments.Add(fileName)
					cbxAttachment.Items.Add(System.IO.Path.GetFileName(fileName))
				Next fileName
				' Selects the last item.
				cbxAttachment.SelectedIndex = cbxAttachment.Items.Count - 1

				btnRemoveAttachment.Enabled = True
				_changed = True
				saveButton.Enabled = True
				saveAttachmentsButton.Enabled = True
				If b = False Then ' sets the title if needed.
					SetTitle()
				End If
			Catch
				MessageBox.Show(dlg.FileName & " is not a file", "Error")
			End Try
		End Sub

		Private Sub btnRemoveAttachment_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnRemoveAttachment.Click
			Dim b As Boolean = _changed

			' Removes an attachment from the collection.
			_attachments.RemoveAt(cbxAttachment.SelectedIndex)

			If _attachments.Count > 0 Then
				' and the combo box.
				cbxAttachment.Items.RemoveAt(cbxAttachment.SelectedIndex)
			Else
				cbxAttachment.SelectedItem = Nothing
				cbxAttachment.Items.Clear()
			End If

			If cbxAttachment.Items.Count = 0 Then
				' Disables the "Remove" button. 
				btnRemoveAttachment.Enabled = False
				_attachments = Nothing

				saveAttachmentsButton.Enabled = False
			ElseIf cbxAttachment.SelectedIndex = -1 Then
				cbxAttachment.SelectedIndex = cbxAttachment.Items.Count - 1
			End If
			_changed = True
			saveButton.Enabled = True
			If b = False Then
				SetTitle()
			End If
		End Sub
	End Class
End Namespace