EMailSend, sends an eMail

List

Questa pagina fa parte del Manuale Programmazione IEC 61131-3. Vai all indice.

Questo blocco funzione da eseguire in task Back, esegue l’invio di una eMail, collegando direttamente all’ingresso File l’uscita del FB SysTCPClient si gestirà una connessione non crittografata, inserendo il FB SysTLSClient verrà gestita la crittografia.

In Domain, Username e Password definire le credenziali di accesso del server SMTP di inoltro. Attivando Send viene eseguito l’invio di una email all’indirizzo definito in Recipient, con l’oggetto definito in Subject e con il testo definito in Body, il testo della mail può contenere solo stringhe ascii. Nel caso il testo da inviare sia molto grande è possibile abilitarne l’invio chunked. Definendo in BChunked l’indirizzo di una variabile BOOL il FB setta la variabile per richiedere l’invio di un chunk di dati. Il programma trasferito nel buffer puntato da Body il testo da inviare resetta la variabile. In questo modo è possibile suddividere il corpo della mail in chunks, terminato l’invio il programma dovrà settare BChunked a eNULL ed attendere la flag Sent di fine invio.

Terminata l’esecuzione si attiva l’uscita Done che rimane attiva sino alla disabilitazione di Send, in questo modo è possibile gestire i FB in cascata. L’uscita Sent si attiva per un loop se l’invio della eMail è andato a buon fine. In caso di errore si attiva per un loop l’uscita Fault.

Mail relay

Nel caso il FB sia eseguito su di un sistema che non supporta la crittografia è possibile aggirare il problema affidandosi ad un servizio di mail relay installato su di un PC all’interno della propria rete. In questo modo il FB invierà la mail non crittografata al mail relay che ne eseguirà il reinvio crittografandola al server esterno SMP configurato. Esistono molti programmi di mail relay free come ad esempio questo, leggere questa nota per la configurazione.

Upgrade list

Gli oggetti obsoleti sono inseriti nella libreria eLLabObsoleteLib fare riferimento al relativo manuale ed al manuale programmazione in formato pdf.

EMailSend_v1

Eliminata gestione interna del client TCP, ora viene passato alla funzione lo stream di comunicazione sul parametro File. Aggiunta uscita Connect per gestire connessione al server. Il parametro BChunked permette di gestire l’invio chunked del corpo della mail, in questo modo è possibile inviare mail di grosse dimensioni.

Information Circle

Blocco funzione

CODESYS: Non disponibile

LogicLab: eLLabNetworkLib

Descrizione

Send (BOOL) Comando invio eMail.
SpyOn (BOOL) Se attivo permette di spiare il funzionamento della FB (Vedi articolo).
BChunked (@BOOL) Definizione variabile BOOL di gestione invio corpo eMail in modo chunked.
File (eFILEP) Stream di comunicazione con server SMTP.
Domain (@STRING) Puntatore stringa definizione dominio invio eMail.
Username (@STRING) Puntatore stringa definizione nome utente accesso server SMTP.
Password (@STRING) Puntatore stringa definizione password accesso server SMTP.
Sender (@STRING) Puntatore stringa definizione indirizzo email mittente.
Recipient (@STRING) Puntatore stringa definizione indirizzo email destinatario.
Subject (@STRING) Puntatore stringa definizione oggetto eMail.
Body (@STRING) Puntatore stringa contenuto eMail.
Timeout (REAL) Tempo limite di esecuzione FB (S).
Done (BOOL) Si attiva al termine della esecuzione comando. Disabilitare Send per disattivarla.
Fault (BOOL) Attivo per un loop se errore esecuzione comando.
Connect (BOOL) Comando di connessione al server, su attivazione occorre gestire la connessione.
Sent (BOOL) Attivo per un loop se l’invio della eMail è riuscito.
STime (REAL) Tempo necessario all’ivio della mail (S).
SMails (UDINT) Contatore numero di mail inviate, si incrementa ad ogni invio corretto della mail.
Errors (UDINT) Contatore errori di esecuzione.

Immagine FB EMailSend

Trigger di spy

Se SpyOn attivo è possibile utilizzare la console di spionaggio per verificare il funzionamento della FB. Sono previsti vari livelli di triggers.

Livelli di trigger
TriggerDescrizione
16#00000001Tx: Comandi inviati al server SMTP.
16#00000002Rx: Stringhe di risposta dal server SMTP.
16#10000000Lg: Messaggio di log.
16#40000000Er: Messaggio di errore

Esempi

Come utilizzare gli esempi.

ST_EMailSend: Attivando Send da debug viene inviata una eMail all’indirizzo indicato in Recipient.

ST_TLSEMailSend: Attivando Send da debug viene inviata una eMail all’indirizzo indicato in Recipient, l’invio è eseguito con crittografia TLS. Nell’esempio viene utilizzato come server SMTP Virgilio perchè GMail dopo le ultime policy di sicurezza non accetta più eMail da dispositivi non certificati.

ST_SendFileByEMail: Attivando Send da debug viene inviato per eMail il contenuto del file di log di sistema C:/System/Logs.txt all’indirizzo indicato in Recipient. Il contenuto del file è appoggiato in un buffer  di memoria rilocabile (SysRMalloc) allocata allo scopo.

LogicLab (Ptp119, ST_EMailSend)
PROGRAM ST_EMailSend
VAR
    i : UDINT; (* Auxiliary counter *)
    Send : BOOL; (* Send mail command *)
    SendNr : UINT; (* Send number *)
    SendErrors : UINT; (* Send errors *)
    Subject : STRING[ 32 ]; (* eMail subject *)
    Body : STRING[ 64 ]; (* eMail body *)
    TCPClient : SysTCPClient; (* TCP client management *)
    Mailer : EMailSend_v1; (* EMailSend FB *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_EMailSend"
// *****************************************************************************
// Setting by debug the "Send" variable a email is sent.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // Initialize the mailer.

    IF (SysFirstLoop) THEN

        // Set TCPClient parameters.

        TCPClient.PeerAdd:=ADR('out.virgilio.it'); //Peer address
        TCPClient.PeerPort:=25; //Peer port
        TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPClient.LocalPort:=0; //Local port
        TCPClient.FlushTm:=10; //Flush time (mS)
        TCPClient.LifeTm:=20; //Life time (S)
        TCPClient.RxSize:=512; //Rx buffer size
        TCPClient.TxSize:=1024; //Tx buffer size

        // Set Mailer parameters.
        // If any parameters has a "$" inside use "$$"

        Mailer.SpyOn:=TRUE; //Spy On
        Mailer.BChunked:=eNULL; //Body chunked management
        Mailer.Domain:=ADR('domain.com'); //Domain address
        Mailer.Username:=ADR('username'); //Access user name
        Mailer.Password:=ADR('password'); //Access password
        Mailer.Sender:=ADR('[email protected]'); //Sender address
        Mailer.Recipient:=ADR('[email protected]'); //Recipient address
        Mailer.Subject:=ADR(Subject); //eMail subject
        Mailer.Body:=ADR(Body); //eMail data
        Mailer.Timeout:=5.0; //Timeout (S)
    END_IF;

    // -------------------------------------------------------------------------
    // MANAGE CONNECTION
    // -------------------------------------------------------------------------
    // Manage the connection.

    TCPClient(Connect:=Mailer.Connect); //TCP client management
    Mailer(File:=TCPClient.File); //Mailer client
    IF (Mailer.Fault) THEN SendErrors:=SendErrors+1; END_IF;
    Mailer.Send:=FALSE; //Send EMail

    // -------------------------------------------------------------------------
    // EMAIL SENDING
    // -------------------------------------------------------------------------
    // If the send command is set the email is sent.

    IF NOT(Send) THEN RETURN; END_IF;
    Send:=FALSE; //Send mail command
    SendNr:=SendNr+1; //Send number

    // eMail subject.

    i:=SysVsnprintf(ADR(Subject), SIZEOF(Subject), ADR('eMail test send Nr:%d'), UINT_TYPE, ADR(SendNr));

    // eMail body.

    i:=SysVsnprintf(ADR(Body), SIZEOF(Body), ADR('This is eMail Nr:%d$r$n'), UINT_TYPE, ADR(SendNr));
    i:=SysCVsnprintf(ADR(Body), SIZEOF(Body), ADR('Till now we have experienced %d error(s)'), UINT_TYPE, ADR(SendErrors));
    Mailer.Send:=TRUE; //Send eMail

// [End of file]
LogicLab (Ptp119, ST_TLSEMailSend)
PROGRAM ST_TLSEMailSend
VAR
    i : UDINT; (* Auxiliary counter *)
    Send : BOOL; (* Send mail command *)
    SendNr : UINT; (* Send number *)
    SendErrors : UINT; (* Send errors *)
    Subject : STRING[ 32 ]; (* eMail subject *)
    Body : STRING[ 64 ]; (* eMail body *)
    TCPClient : SysTCPClient; (* TCP client management *)
    TLSClient : SysTLSClient; (* TLS client *)
    Mailer : EMailSend_v1; (* EMailSend FB *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_TLSEMailSend"
// *****************************************************************************
// Setting by debug the "Send" variable a email is sent.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // Initialize the mailer.

    IF (SysFirstLoop) THEN

        // Set TCPClient parameters.

        TCPClient.PeerAdd:=ADR('out.virgilio.it'); //Peer address
        TCPClient.PeerPort:=465; //Peer port
        TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPClient.LocalPort:=0; //Local port
        TCPClient.FlushTm:=10; //Flush time (mS)
        TCPClient.LifeTm:=20; //Life time (S)
        TCPClient.RxSize:=512; //Rx buffer size
        TCPClient.TxSize:=1024; //Tx buffer size

        // Set TLSClient parameters.

        TLSClient.SpyOn:=TRUE; //Spy active
        TLSClient.Mode:=TLS_MODE_TCP; //TLS mode
        TLSClient.Server:=TCPClient.PeerAdd; //Server name
        TLSClient.CipherSuites:=eNULL; //Cipher suites supported
        TLSClient.Psk:=eNULL; //Preshared key
        TLSClient.PskIdentity:=eNULL; //Preshared key identity

        // Without server certification.

        TLSClient.CAVerify:=TLS_CA_NONE; //Certificates verify type
        TLSClient.CAFile:=eNULL; //CA file

        // With server certification.

        // TLSClient.CAVerify:=TLS_CA_REQUIRED; //Certificates verify type
        // TLSClient.CAFile:=ADR('/home/pi/Certificates/cacert.pem'); //CA file

        // Set Mailer parameters.
        // If any parameters has a "$" inside use "$$"

        Mailer.SpyOn:=TRUE; //Spy On
        Mailer.BChunked:=eNULL; //Body chunked management
        Mailer.Domain:=ADR('virgilio.it'); //Domain address
        Mailer.Username:=ADR('username'); //Access user name
        Mailer.Password:=ADR('password'); //Access password
        Mailer.Sender:=ADR('[email protected]'); //Sender address
        Mailer.Recipient:=ADR('[email protected]'); //Recipient address
        Mailer.Subject:=ADR(Subject); //eMail subject
        Mailer.Body:=ADR(Body); //eMail data
        Mailer.Timeout:=5.0; //Timeout (S)
    END_IF;

    // -------------------------------------------------------------------------
    // MANAGE CONNECTION
    // -------------------------------------------------------------------------
    // Manage the connection.

    TCPClient(Connect:=Mailer.Connect); //TCP client management
    TLSClient(IFile:=TCPClient.File); //TLS client management
    Mailer(File:=TLSClient.OFile); //Mailer client
    IF (Mailer.Fault) THEN SendErrors:=SendErrors+1; END_IF;
    Mailer.Send:=FALSE; //Send EMail

    // -------------------------------------------------------------------------
    // EMAIL SENDING
    // -------------------------------------------------------------------------
    // If the send command is set the email is sent.

    IF NOT(Send) THEN RETURN; END_IF;
    Send:=FALSE; //Send mail command
    SendNr:=SendNr+1; //Send number

    // eMail subject.

    i:=SysVsnprintf(ADR(Subject), SIZEOF(Subject), ADR('eMail test send Nr:%d'), UINT_TYPE, ADR(SendNr));

    // eMail body.

    i:=SysVsnprintf(ADR(Body), SIZEOF(Body), ADR('This is eMail Nr:%d$r$n'), UINT_TYPE, ADR(SendNr));
    i:=SysCVsnprintf(ADR(Body), SIZEOF(Body), ADR('Till now we have experienced %d error(s)'), UINT_TYPE, ADR(SendErrors));
    Mailer.Send:=TRUE; //Send eMail

// [End of file]
LogicLab (Ptp119, ST_SendFileByEMail)
PROGRAM ST_SendFileByEMail
VAR
    i : UDINT; (* Auxiliary counter *)
    Fp : eFILEP; (* File pointer *)
    FPos : DINT; (* File read position *)
    Send : BOOL; (* Send mail command *)
    BChunked : BOOL; (* Body chunked management *)
    FLength : DINT; (* File length *)
    SendNr : UINT; (* Send number *)
    ErrorNr : USINT; (* Error number *)
    CaseNr : USINT; (* Case number *)
    BDSize : INT := 500; (* Body data size (SysRMalloc) *)
    CaseBk : USINT; (* Case back *)
    Filename : STRING[ 32 ]; (* File to send *)
    Subject : STRING[ 32 ]; (* eMail subject *)
    TCPClient : SysTCPClient; (* TCP client management *)
    Mailer : EMailSend_v1; (* EMailSend FB *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_SendFileByEMail"
// *****************************************************************************
// Setting by debug the "Send" variable an email with the content of defined
// file is sent.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // Initialize the mailer.

    IF (SysFirstLoop) THEN

        // Set TCPClient parameters.

        TCPClient.PeerAdd:=ADR('out.virgilio.it'); //Peer address
        TCPClient.PeerPort:=25; //Peer port
        TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPClient.LocalPort:=0; //Local port
        TCPClient.FlushTm:=10; //Flush time (mS)
        TCPClient.LifeTm:=20; //Life time (S)
        TCPClient.RxSize:=512; //Rx buffer size
        TCPClient.TxSize:=1024; //Tx buffer size

        // Set Mailer parameters.
        // If any parameters has a "$" inside use "$$"

        Mailer.SpyOn:=TRUE; //Spy On
        Mailer.Domain:=ADR('domain.com'); //Domain address
        Mailer.Username:=ADR('username'); //Access user name
        Mailer.Password:=ADR('password'); //Access password
        Mailer.Sender:=ADR('[email protected]'); //Sender address
        Mailer.Recipient:=ADR('[email protected]'); //Recipient address
        Mailer.Subject:=ADR(Subject); //eMail subject
        Mailer.Timeout:=5.0; //Timeout (S)
    END_IF;

    // -------------------------------------------------------------------------
    // MANAGE CONNECTION
    // -------------------------------------------------------------------------
    // Manage the connection.

    TCPClient(Connect:=Mailer.Connect); //TCP client management
    Mailer(File:=TCPClient.File); //Mailer client
    IF (Mailer.Fault) THEN ErrorNr:=10; CaseNr:=0; END_IF;
    Mailer.Send:=FALSE; //Send EMail

    // -------------------------------------------------------------------------
    // PROGRAM CASES
    // -------------------------------------------------------------------------
    // Manage the program cases. 

    CASE (CaseNr) OF

        // ---------------------------------------------------------------------
        // Free body data memory..

        0:
        IF (Mailer.Body <> eNULL) THEN i:=SysRMFree(ADR(Mailer.Body)); END_IF;

        // Waits the "Send" command and allocate the body buffer.

        IF NOT(Send) THEN RETURN; END_IF;
        IF NOT(SysRMAlloc(BDSize, ADR(Mailer.Body))) THEN RETURN; END_IF;
        Send:=FALSE; //Send mail command

        // eMail subject.

        SendNr:=SendNr+1; //Send number
        i:=SysVsnprintf(ADR(Subject), SIZEOF(Subject), ADR('eMail test send Nr:%d'), UINT_TYPE, ADR(SendNr));

        // Acquire file length and start mail sending.

        FPos:=0; //File read position
        BChunked:=FALSE; //Body chunked management
        Filename:='C:/System/Logs.txt'; //File to send
        FLength:=SysGetFileLen(ADR(Filename)); //File length
        Mailer.BChunked:=ADR(BChunked); //Body chunked management
        Mailer.Send:=TRUE; //Send eMail
        CaseNr:=CaseNr+1; //Case number

        // ---------------------------------------------------------------------
        // On data chunk request data are read out from the file.

        1:
        IF NOT(BChunked) THEN RETURN; END_IF;
        CaseBk:=CaseNr+1; //Case back
        CaseNr:=100; //Read data from file
        
        // ---------------------------------------------------------------------
        // Resetting "BChunked" the chunk of data is inserted on the mail body.

        2:
        BChunked:=FALSE; //Body chunked management
        IF (FPos < FLength) THEN CaseNr:=CaseNr-1; RETURN; END_IF;

         // If file position is equal to file length, file entirely read.

        Mailer.BChunked:=eNULL; //Body chunked management
        CaseNr:=CaseNr+1; //Case number

        // ---------------------------------------------------------------------
        // Last chunk, wait email sent.

        3:
        IF NOT(Mailer.Sent) THEN RETURN; END_IF;
        CaseNr:=0;  //Case number

        // ---------------------------------------------------------------------
        // READ DATA FROM FILE
        // ---------------------------------------------------------------------
        // Open the file, exit on error.

        100:
        Fp:=SysFfopen(ADR(Filename), ADR('r')); //File pointer
        IF (Fp = eNULL) THEN ErrorNr:=20; CaseNr:=0; RETURN; END_IF;

        // Set position to read on file.
        // On error, there is not more lines to read.

        IF (Sysfseek(Fp, FPos, ID_SEEK_SET) = eEOF) THEN
            Fp:=Sysfclose(Fp); //Close file
            ErrorNr:=30; //Error number
            CaseNr:=0; //Case number
            RETURN;
        END_IF;

        // Read a line from file.
        // "-1" to save space for null string terminator.

        i:=Sysmemset(Mailer.Body, 0, BDSize); //Clear body data
        FPos:=FPos+Sysfread(Mailer.Body, BDSize-1, 1, Fp); //File read position
        Fp:=Sysfclose(Fp); //Close file
        CaseNr:=CaseBk; //To read data from file
    END_CASE;

// [End of file]
Was this article helpful?