lunedì 25 giugno 2018

VSTO .Net trasformare una email di tipo msg in EML per le pec in VB

Si riporta l'articolo scritto per il sito https://www.iprogrammatori.it/articoli/programmazione/art_net-vsto-trasformare-una-email-di-tipo-m_1574.aspx


In questo articolo vedremo come convertire una email nel formato Outlook 2016 che ha l’estensione “.msg” nel formato universale per altri client email di tipo “.eml”.
Inoltre si sperimenterà la conversione su una email di tipo “PEC” con all’interno del messaggio un allegato, fornendo così al lettore interessanti spunti per realizzare programmi o gestire i propri progetti .Net nel modo migliore.
Il tutto verrà illustrato con i linguaggi di programmazione più usati per la tecnologia .Net in particolare con il linguaggio VB.Net e C#

Stesura del codice

Si crea un nuovo progetto di tipo VSTO con Visual Studio 2017 community o altre versione.
Nella creazione del progetto, selezionare il linguaggio di proprio interesse, nelle varie sotto voci, fare click sulla voce “Office/Sharepoint” e nel sotto menu selezionare “Componenti Aggiuntivi” a questo punto, nella parte dei modelli (parte centrale) selezionare il modello di tipo “Componente aggiuntivo per Outlook 201x” dove la X sta indicando la versione (2016 o 2013).
Facciamo click sulla classe (o file) denominato “ThisAddin” presente per i due linguaggi.
In alto, sopra ogni dichiarazione, scriviamo lo spazio dei nomi per gestire alcuni aspetti del codice per fare uso delle classi per realizzare il nostro esempio.
Qui di seguito si riporta la dichiarazione dei spazio dei nomi per entrambi i linguaggi.


VB.Net

Imports System.Net.Mail

Imports System.IO

 

C#

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Xml.Linq;

using Outlook = Microsoft.Office.Interop.Outlook;

using Office = Microsoft.Office.Core;

 

 

using System.Windows.Forms;

using System.IO;

using System.Net.Mail;


A questo punto dobbiamo creare a livello di classe, due oggetti per la creazione della barra e del pulsante che al click verrà eseguito la conversione del file
Qui di seguito le dichiarazioni per entrambi i linguaggi.



VB.Net

Dim ComBar As Office.CommandBar

    Dim pulsante As Office.CommandBarButton

C#

  Microsoft.Office.Core.CommandBar ComBar;

        Microsoft.Office.Core.CommandBarButton pulsante;


Si continua a scrivere le istruzioni per la creazione della barra e del pulsante, e la gestione dell’evento click del pulsante.
Qui di seguito tali dichiarazione.



VB.Net

Private Sub CreaBarra()

        ComBar = Globals.ThisAddIn.Application.ActiveExplorer().CommandBars.Add("Esempio EML", Office.MsoBarPosition.msoBarTop, False, True)

        ComBar.Protection = Office.MsoBarProtection.msoBarNoCustomize

        ComBar.Visible = True

    End Sub

 

 

    Private Sub CreaPulsante()

        'aggiungo il pulsante alla barra ed imposto la proprietà testo oltre al gestore di evento click

        pulsante = TryCast(ComBar.Controls.Add(Office.MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, True), Office.CommandBarButton)

        pulsante.Caption = "Salva Formato EML VB"

        pulsante.Style = Office.MsoButtonStyle.msoButtonIconAndCaption

        pulsante.TooltipText = "Salva l'email in formato eml."

        pulsante.FaceId = 2605

 

        AddHandler pulsante.Click, AddressOf pulsante_Click

 

    End Sub

 

C#

   private void CreaBarra()

        {

            ComBar = Globals.ThisAddIn.Application.ActiveExplorer().CommandBars.Add(

                   "Esempio EML",

                   Office.MsoBarPosition.msoBarTop,

                   false,

                   true);

            ComBar.Protection = Office.MsoBarProtection.msoBarNoCustomize;

            ComBar.Visible = true;

        }

 

        //funzione per la creazione del pulsante

        private void CreaPulsante()

        {

            //aggiungo il pulsante alla barra ed imposto la proprietà testo oltre al gestore di evento click

            pulsante = ComBar.Controls.Add(Office.MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, true) as Office.CommandBarButton;

            pulsante.Caption = "Salva Formato EML";

            pulsante.Style = Office.MsoButtonStyle.msoButtonIconAndCaption;

            pulsante.TooltipText = "Salva l'email in formato eml.";

            pulsante.FaceId = 2605;

            //gestore dell'evento click

            pulsante.Click += new Office._CommandBarButtonEvents_ClickEventHandler(pulsante_Click);

        }


Queste funzioni saranno richiamate nell’evento “StartUp del compoenente.
Qui di seguito il codice.



VB.Net

Private Sub ThisAddIn_Startup() Handles Me.Startup

        CreaBarra()

        CreaPulsante()

    End Sub

C#

private void ThisAddIn_Startup(object sender, System.EventArgs e)

        {

            CreaBarra();

            CreaPulsante();

        }


Nell’evento click del pulsante, scriveremo il codice che permette di gestire l’email, in particolare la possibilità di verificare se l’email selezionata è di tipo pec, in tal caso verranno eseguite le funzioni per l’esportazione.
Qui di seguito si riporta il codice per i linguaggi VB.Net e C#




VB.Net

Private Sub pulsante_Click(Ctrl As Office.CommandBarButton, ByRef CancelDefault As Boolean)

 

        Try

            'Verifico che ho selezionato almeno una email

            If Me.Application.ActiveExplorer().Selection.Count > 0 Then

                Dim PR_ATTACH_DATA_BIN As String = "http://schemas.microsoft.com/mapi/proptag/0x37010102"

                Dim objectSelezionato As [Object] = Me.Application.ActiveExplorer().Selection(1)

 

                If TypeOf objectSelezionato Is Outlook.MailItem Then

                    Dim mailItemSelezionato As Outlook.MailItem = TryCast(objectSelezionato, Outlook.MailItem)

 

 

                    For Each elemento As Outlook.Attachment In mailItemSelezionato.Attachments

                        If elemento.FileName.Contains(".eml") Or elemento.FileName.Contains("daticert.xml") Then

                            Esporta(mailItemSelezionato)

                        End If

                    Next

                End If

 

 

            End If

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show("Errore: " + ex.Message)

        End Try

 

 

 

    End Sub

C#

void pulsante_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)

        {

 

            try

            {

                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

 

                //Verifico che ho selezionato almeno una email

                if (this.Application.ActiveExplorer().Selection.Count > 0)

                {

                    Object selObject = Application.ActiveExplorer().Selection[1];

                    if (selObject is Outlook.MailItem)

                    {

                        Outlook.MailItem mailItemSelezionato =

                            (selObject as Outlook.MailItem);

                        foreach (Outlook.Attachment elemento in mailItemSelezionato.Attachments)

                        {

                            if (elemento.FileName.Contains(".eml") || elemento.FileName.Contains("daticert.xml"))

                            {

                                Esporta(mailItemSelezionato);

                            }

                        }

 

 

 

                    }

                    else

                    {

                        System.Windows.Forms.MessageBox.Show("Selezionare una email", "", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    }

                }

 

            }

            catch (Exception ex)

            {

                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

                System.Windows.Forms.MessageBox.Show("Si è verificato il seguente errore: " + ex.Message);

            }

            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

 

        }


Si riporta il codice per la gestione dell’esportazione nel quale verrà creato un oggetto di tipo mailMessage, con il quale si generà il file di tipo eml con le informazioni e dati presenti nell’oggetto di tipo mailItem.
La funzione avrà il compito di trasformare i due oggetti e cancellare i file temporanei.
Qui di seguito le dichiarazioni per entrambi i linguaggi.


VB.Net

Private Sub Esporta(ByVal mailItemSelezionato As Outlook.MailItem)

        Try

            Dim application As Outlook.Application = New Outlook.Application()

 

            For Each elemento As Outlook.Attachment In mailItemSelezionato.Attachments

                If elemento.FileName.Contains(".eml") Then

                    Dim percorsoTemporaneo As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\TempFile\"

                    If Directory.Exists(percorsoTemporaneo) = False Then

                        Directory.CreateDirectory(percorsoTemporaneo)

                    End If

 

                    elemento.SaveAsFile(percorsoTemporaneo & "\" + elemento.FileName)

                    Dim mailItemEsistente As Outlook.MailItem = application.CreateItemFromTemplate(percorsoTemporaneo & "\" + elemento.FileName)

                    Dim mailMessaggeNuovo As New MailMessage()

                    mailMessaggeNuovo.From = New System.Net.Mail.MailAddress(mailItemEsistente.SenderEmailAddress)

                    mailMessaggeNuovo.[To].Add(mailItemEsistente.[To])

                    mailMessaggeNuovo.Body = mailItemEsistente.Body

                    If Not String.IsNullOrEmpty(mailItemEsistente.CC) Then mailMessaggeNuovo.CC.Add(mailItemEsistente.CC)

                    If Not String.IsNullOrEmpty(mailItemEsistente.BCC) Then mailMessaggeNuovo.Bcc.Add(mailItemEsistente.BCC)

                    mailMessaggeNuovo.Subject = mailItemEsistente.Subject

                    If mailItemEsistente.Attachments.Count > 0 Then

                        For Each allegatoPec As Outlook.Attachment In mailItemEsistente.Attachments

                            allegatoPec.SaveAsFile(percorsoTemporaneo & "\" + allegatoPec.FileName)

                            mailMessaggeNuovo.Attachments.Add(New System.Net.Mail.Attachment(percorsoTemporaneo & "\" + allegatoPec.FileName))

 

                        Next

                    End If

 

                    Dim emailConvertita As String = ConvertiEmailInEML(mailMessaggeNuovo)

                    

                    File.Delete(emailConvertita)

                    Directory.Delete(Path.GetDirectoryName(emailConvertita))

                    File.Delete(percorsoTemporaneo & "\" + elemento.FileName)

 

                End If

            Next

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show("Si è verificato il seguente errore: " & ex.Message)

        End Try

    End Sub

C#

  private void Esporta(Outlook.MailItem mailItemSelezionato)

        {

            try

            {

                Outlook.Application application = new Outlook.Application();

                const string PR_ATTACH_DATA_BIN = "http://schemas.microsoft.com/mapi/proptag/0x37010102";

                foreach (Outlook.Attachment elemento in mailItemSelezionato.Attachments)

                {

                    if (elemento.FileName.Contains(".eml"))

                    {

                        string percorsoTemporaneo = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

                        elemento.SaveAsFile(percorsoTemporaneo + "\\" + elemento.FileName);

 

                        Outlook.MailItem mailItemEsistente = application.CreateItemFromTemplate(percorsoTemporaneo + "\\" + elemento.FileName);

 

                         MailMessage mailMessaggeNuovo = new  MailMessage();

                        mailMessaggeNuovo.From = new System.Net.Mail.MailAddress(mailItemEsistente.SenderEmailAddress);

                        mailMessaggeNuovo.To.Add(mailItemEsistente.To);

                        mailMessaggeNuovo.Body = mailItemEsistente.Body;

                        if (!string.IsNullOrEmpty(mailItemEsistente.CC))

                            mailMessaggeNuovo.CC.Add(mailItemEsistente.CC);

                        if (!string.IsNullOrEmpty(mailItemEsistente.BCC))

                            mailMessaggeNuovo.Bcc.Add(mailItemEsistente.BCC);

                        mailMessaggeNuovo.Subject = mailItemEsistente.Subject;

                        //Allegato

                        if (mailItemEsistente.Attachments.Count > 0)

                        {

                            foreach (Outlook.Attachment allegatoPec in mailItemEsistente.Attachments)

                            {

                                mailMessaggeNuovo.Attachments.Add(new System.Net.Mail.Attachment(new MemoryStream(allegatoPec.PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN)), allegatoPec.FileName));

                            }

 

                        }

                        string emailConvertita = ConvertiEmailInEML(mailMessaggeNuovo);

                        File.Delete(emailConvertita);

                        Directory.Delete(Path.GetDirectoryName(emailConvertita));

 

                        File.Delete(percorsoTemporaneo + "\\" + elemento.FileName);

 

 

 

                    }

                }

 

 

            }

            catch (Exception ex)

            {

 

                System.Windows.Forms.MessageBox.Show("Si è verificato il seguente errore: " + ex.Message);

            }

 

 

 

 

        }



Siamo giunti all’ultima parte della stesura del codice.
La funzione ConvertiEmailinEml permetterà di trasformare in un file sul computer l’email nel formato “eml” tramite la classe smtclient, che impostando la proprietà “PickupDirectoryLocation” genera un file.
Si riporta il frammento di codice per entrambi i linguaggi.



VB.Net

Private Function ConvertiEmailInEML(ByVal mailMessaggeNuovo As MailMessage) As String

        Try

            mailMessaggeNuovo.SubjectEncoding = System.Text.Encoding.UTF8

            mailMessaggeNuovo.BodyEncoding = System.Text.Encoding.UTF8

            mailMessaggeNuovo.Headers.Add("X-VirusFound", "false")

            mailMessaggeNuovo.Headers.Add("X-Spam", "Score=1.5")

            Using clientSMTP = New SmtpClient()

                Dim id = Guid.NewGuid()

                Dim CartellaTemporanea = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)

                CartellaTemporanea = Path.Combine(CartellaTemporanea, "TempEmail")

                CartellaTemporanea = Path.Combine(CartellaTemporanea, id.ToString())

                If Not Directory.Exists(CartellaTemporanea) Then

                    Directory.CreateDirectory(CartellaTemporanea)

                End If

 

                clientSMTP.UseDefaultCredentials = True

                clientSMTP.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.SpecifiedPickupDirectory

                clientSMTP.PickupDirectoryLocation = CartellaTemporanea

                clientSMTP.Send(mailMessaggeNuovo)

                Dim percorsoFileEML = Directory.GetFiles(CartellaTemporanea).Single()

                Return percorsoFileEML

            End Using

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show("Si è verificato il seguente errore: " & ex.Message)

            Return ""

        End Try

    End Function

C#

  private string ConvertiEmailInEML(MailMessage mailMessaggeNuovo)

        {

            try

            {

                mailMessaggeNuovo.SubjectEncoding = System.Text.Encoding.UTF8;

                mailMessaggeNuovo.BodyEncoding = System.Text.Encoding.UTF8;

                //intestazione da aggiungerne altre se si vuole

                mailMessaggeNuovo.Headers.Add("X-VirusFound", "false");

                mailMessaggeNuovo.Headers.Add("X-Spam", "Score=1.5");

 

 

                using (var clientSMTP = new  SmtpClient())

                {

                    var id = Guid.NewGuid();

 

                    var CartellaTemporanea = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

 

                    CartellaTemporanea = Path.Combine(CartellaTemporanea, "TempEmail");

 

                   

                    CartellaTemporanea = Path.Combine(CartellaTemporanea, id.ToString());

 

                    if (!Directory.Exists(CartellaTemporanea))

                    {

                        Directory.CreateDirectory(CartellaTemporanea);

                    }

 

                    clientSMTP.UseDefaultCredentials = true;

 

                    clientSMTP.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.SpecifiedPickupDirectory;

                    //indico che viene generato il file anzichè spedito

                    clientSMTP.PickupDirectoryLocation = CartellaTemporanea;

                    clientSMTP.Send(mailMessaggeNuovo);

 

                    var percorsoFileEML = Directory.GetFiles(CartellaTemporanea).Single();

                    return percorsoFileEML;

 

                }

            }

            catch (Exception ex)

            {

 

                System.Windows.Forms.MessageBox.Show("Si è verificato il seguente errore: " + ex.Message);

                return "";

            }

        }



Conclusioni

L’articolo ha voluto fornire interessanti spunti sulla programmazione Office, in particolare con Outlook tramite la tecnologia VSTO, realizzando un componente aggiuntivo che permette di convertire una email di Outlook in un file di tipo “eml” ma solo se tale email è di tipo “PEC”.
Le potenzialità offerte da questa tecnologia, rendono facile lo sviluppo di Office ed al tempo stesso di estendere le funzionalità del pacchetto office, in questo caso di Microsoft Office Outlook, con interessanti aspetti che il programmatore vuole aggiungere.

Nessun commento: