Creating QR codes and emailing them in a pdf as an attachment from the IBM i
QR codes are very much in the news at the moment. QR codes are basically 2D barcodes but with the ability to contain a greater amount of information that can be read much faster and more accurately than a barcode.
Barcodes were developed back in the 1960s in Japan to address the need for cashiers to be able to automatically scan products from the basket to the shopping bag without having to manually key in the details for each purchased item. Barcodes are great but with the need to be able to squeeze more and more data into the barcode a new format was required. At Denso Wave development engineer Masahiro Hara pioneered the new QR code format that the company launched into the world in 1994 in order to meet the needs of their customers who were craving greater amounts of information to be more easily captured.
Barcodes are typically read by an LED or laser scanner that bounces a red beam of light off the barcode and then back into a photoelectric cell. The rate and number of pulses of light that hit the photoelectric cell determine the characters that are encoded into the barcode. QR code scanners grab an image of the 2D barcode using a camera and then software analyses the image to find key reference points that tell the program where to start looking for the characters that have been encoded into the QR code. QR code optical scanners have the added advantage that they can read QR codes and barcodes that are displayed on a screen. This means they can read codes that have been sent to a mobile phone. LED and laser scanners fail in this regard as they cannot bounce light back from a mobile phone or LCD flat panel display.
The QR code scanner pictured above is an entry level scanner that can be purchased online for around forty GB pounds.
The following code snippet allows a barcode to be created on the IBM i and then emailed out as an attachment. First off we have an SQLRPGLE program that builds some of the parameters to be used in the process.
dcl-s addAttchMt char(100); dcl-s body char(1000); dcl-s subject char(80); dcl-s qCmd char(2000); dcl-pr QCMDEXC extpgm ; *n char(250) options(*varsize) const; *n packed(15:5) const; end-pr; // ******************** begsr SendBarcodeEmail; // ******************** // Create temorary file name for PDF file in /tmp exec sql SET :addAttchMt='/tmp/' CONCAT 'FILENAME' CONCAT VARCHAR_FORMAT(CURRENT TIMESTAMP, 'YYYYMMDDHH24MISSNNNNNN') CONCAT TRIM(CHAR(INT(RAND()*10000))) CONCAT '.pdf'; // Format subject text subject='This is the subject of the QR code email.'; // Format body text body='Hi,<br>'+ '<br>'+ 'This is an example QR code email.<br>'+ '<br>'+ 'best regards+'<br>'; // Call program to create exit barcode and send as an email attachment qCmd='SBMJOB CMD(SENDBARCD '+ 'SETFROM(''example_qr_code_email@example.com'') '+ 'ADDADDRESS(''receiver@example.com'') '+ 'ADDATTCHMT('''+%trim(addAttchMt)+''') '+ 'SUBJECT('''+%trim(Subject)+''') '+ 'BODY('''+%trim(body)+''') '+ 'QRCODE(''This is some sample data to be encoded ion the QR code'')) '+ 'JOBQ(QBATCH/QGPL) USER(QPGMR)'; QCMDEXC(qCmd:%len(%trimr(qCmd))); // *** endsr; // ***
The following command source prompts the parameters for the program that creates the barcode pdf file.
CMD PROMPT('Exit barcode PDF create & send') PARM KWD(SETFROM) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email from address') PARM KWD(ADDADDRESS) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('To address') PARM KWD(ADDATTCHMT) TYPE(*CHAR) LEN(100) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('FQPN of PDF attachment') PARM KWD(SUBJECT) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email subject') PARM KWD(BODY) TYPE(*CHAR) LEN(1000) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email body') PARM KWD(QRCODE) TYPE(*CHAR) LEN(26) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Number to be barcoded')
Then use this CL program to run the barcode creation SQLRPGLE program. Note the workstation customization parameter (WSCST) that redirects the print file output to a PDF streamfile in the IFS.
/* Create exit barcode in embedded PDF file in /tmp and email to receiver */ PGM PARM(&SETFROM &ADDADDRESS &ADDATTCHMT + &SUBJECT &BODY &BARCODE) DCL VAR(&ADDADDRESS) TYPE(*CHAR) LEN(80) DCL VAR(&ADDATTCHMT) TYPE(*CHAR) LEN(100) DCL VAR(&BARCODE) TYPE(*CHAR) LEN(26) DCL VAR(&BODY) TYPE(*CHAR) LEN(1000) DCL VAR(&SETFROM) TYPE(*CHAR) LEN(80) DCL VAR(&SUBJECT) TYPE(*CHAR) LEN(80) /* Erase existing file. (File name unique so should never exist) */ ERASE OBJLNK(&ADDATTCHMT) MONMSG MSGID(CPF0000) /* Create PDF with embedded barcode in /tmp */ OVRPRTF FILE(CRTBCDQR) DEVTYPE(*AFPDS) PAGESIZE(31 + 60) LPI(4) CPI(12) OVRFLW(31) + TOSTMF(&ADDATTCHMT) WSCST(*PDF) + OVRSCOPE(*CALLLVL) CALL PGM(CRTBARCD) PARM(&BARCODE) /* Erase temporary PDF document created in /tmp */ ERASE OBJLNK(&ADDATTCHMT) MONMSG MSGID(CPF0000) ENDPGM
Compile the following print file (PRTF) CRTBCDQR using option 14 in PDM
A R CRTBCDQR1 A SPACEB(001) A TEXTLINE 40A 3 A R CRTBCDQR2 A QRCODE 26A 12BARCODE(QRCODE 1 *HRZ + A X'02' (*WIDTH .05) (*SWIDTH 2.5) + A (*QRCODE 4 1 *CONVERT(1) + A *TRIM *AIMSTD(99)))
This is the ILERPG program to create the QR code
**free // Create QR code PDF file // Novagem Ltd ctl-opt dftactgrp(*NO); dcl-f CRTBCDQR printer usropn; dcl-s #t int(10); dcl-ds msgData; *N char(40) inz('Hi, '); *N char(40) inz(' '); *N char(40) inz('This is an example QR code. '); *N char(40) inz(' '); *N char(40) inz(' '); *N char(40) inz(' '); *N char(40) inz('best regards. '); *N char(40) inz(' '); *N char(40) inz('Best wishes, '); *N char(40) inz('From all the team at '); *N char(40) inz('Novagem Ltd '); *N char(40) inz(' '); msgArray char(40) Dim(12) Pos(1); end-ds; dcl-pi *N; barcode_ like(BARCODE); end-pi; open CRTBCDQR; for #t=1 to %elem(msgArray); msgArray(#t)=%scanrpl('USBIZNAM':USBIZNAM:msgArray(#t)); textline=msgArray(#t); write CRTBCDQR1; endfor; BARCODE=barcode_; write CRTBCDQR2; close CRTBCDQR; *INLR=*ON; return;
Here is the CMD source to send the email with the QR code attachment.
CMD PROMPT('Send Email') PARM KWD(SETFROM) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email from address') PARM KWD(ADDADDRESS) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email to address') PARM KWD(ADDATTCHMT) TYPE(*CHAR) LEN(100) + RSTD(*NO) MIN(0) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('FQPN of PDF attachment') PARM KWD(SUBJECT) TYPE(*CHAR) LEN(80) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email subject') PARM KWD(BODY) TYPE(*CHAR) LEN(1000) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) FULL(*NO) + CASE(*MIXED) PROMPT('Email body')
ILERPG program to end any previous pase environment calls in this job ahead of a call to QP2SHELL.
**free // End PASE environment // Novagem Ltd ctl-opt dftactgrp(*NO) option(*NODEBUGIO); dcl-s rc int(10); dcl-pr Qp2EndPase int(10) extproc('Qp2EndPase') end-pr; // End PASE rc=Qp2EndPase(); // Close program *INLR = *ON; return;
Here is the CL program to submit the PHPMailer script using QP2SHELL that will send the email.
/* Send email using PHPMailer */ PGM PARM(&SETFROM &ADDADDRESS &ADDATTCHMT &SUBJECT &BODY) DCLPRCOPT DFTACTGRP(*NO) ACTGRP(*NEW) DCL VAR(&ADDADDRESS) TYPE(*CHAR) LEN(80) DCL VAR(&ADDATTCHMT) TYPE(*CHAR) LEN(100) DCL VAR(&BODY) TYPE(*CHAR) LEN(1000) DCL VAR(&LEN1) TYPE(*DEC) LEN(5 0) DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00') DCL VAR(&PHPCMD) TYPE(*CHAR) LEN(100) VALUE('/QOpenSys/pkgs/bin/php') DCL VAR(&SCRIPT) TYPE(*CHAR) LEN(100) VALUE('php/sendemail.php') DCL VAR(&SETFROM) TYPE(*CHAR) LEN(80) DCL VAR(&SUBJECT) TYPE(*CHAR) LEN(80) /* Null end variables for QP2SHELL */ CHGVAR VAR(&PHPCMD) VALUE(&PHPCMD *TCAT &NULL) CHGVAR VAR(&SCRIPT) VALUE(&DOCSDIR *TCAT &SCRIPT *TCAT &NULL) CHGVAR VAR(&SETFROM) VALUE(&SETFROM *TCAT &NULL) CHGVAR VAR(&ADDADDRESS) VALUE(&ADDADDRESS *TCAT &NULL) CHGVAR VAR(&ADDATTCHMT) VALUE(&ADDATTCHMT *TCAT &NULL) CHGVAR VAR(&SUBJECT) VALUE(&SUBJECT *TCAT &NULL) CHGVAR VAR(&BODY) VALUE(&BODY *TCAT &NULL) /* End previous PASE environment call in this activation group */ CALL PGM(ENDPASE) /* Run PHP PHPMAiler script to email barcode */ CALL PGM(QP2SHELL) PARM(&PHPCMD &SCRIPT + &SETFROM + &ADDADDRESS + &ADDATTCHMT + &SUBJECT + &BODY) ENDPGM
Here is the sendemail.php PHP script that will send the QR code email using PHPMailer. See the previous article on setting up PHPMailer on the IBM i https://novagem.co.uk/use-opensource-software-phpmailer-to-send-emails-with-attachments-using-sls-or-tls-on-ibm-i/
<?php ini_set('display_startup_errors', 1); ini_set('display_errors', 1); error_reporting(-1); use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require '/QOpenSys/pkgs/lib/PHPMailer/src/Exception.php'; require '/QOpenSys/pkgs/lib/PHPMailer/src/PHPMailer.php'; require '/QOpenSys/pkgs/lib/PHPMailer/src/SMTP.php'; $mail = new PHPMailer(true); // "true" as a parameter enables exceptions try { $mail->SMTPDebug = 4; // 0=no debug output 4=maxiumum debug ouput; $mail->SMTPOptions = array( // Ignore certificate errors, use with caution! 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ) ); $mail->isSMTP(); // Set mailer to use SMTP $mail->CharSet = 'UTF-8'; // Character set for HTML $mail->Host = 'mail.example.com'; // Specify SMTP server host or ip address $mail->Port = 465; // SMTP port $mail->SMTPAuth = true; // Enable SMTP authentication $mail->Username = 'username'; // SMTP username $mail->Password = 'password'; // SMTP password $mail->SMTPSecure = 'ssl'; // Use SMTP encryption $mail->SMTPAutoTLS = true; // Use TLS if available on the server $mail->setFrom($argv[4]); // Email from address $mail->addAddress($argv[5]); // Send to email address if (!empty($argv[6])) $mail->addAttachment($argv[6]); // Add attachment $mail->isHTML(true); // Set email format to HTML $mail->Subject = $argv[7]; // Subject line $mail->Body = $argv[8]; // HTML formatted body text $mail->AltBody = strip_tags(str_replace('<br>', "r\n", $argv[8]),); // Plain text body $mail->send(); } catch (Exception $e) { error_log($argv[0] . " PHPMailer failure: " . $mail->ErrorInfo, 0); } ?>