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.
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.

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
Trigger | Descrizione |
---|---|
16#00000001 | Tx: Comandi inviati al server SMTP. |
16#00000002 | Rx: Stringhe di risposta dal server SMTP. |
16#10000000 | Lg: Messaggio di log. |
16#40000000 | Er: Messaggio di errore |
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]