=====Sending an HTML email with optional attachments=====
//by Richard Russell, April 2014, corrected August 2015//\\ \\ In the article [[/Sending%20an%20email%20with%20attachments|Sending an email with attachments]] the procedure **PROCsendmailattach()** automatically sends an email using the SOCKLIB library. Listed below is a procedure which performs the same function except that you can send the body of the email as **HTML** instead of (or preferably as well as) **plain text**. The procedure might be called as follows:\\
INSTALL @lib$+"SOCKLIB"
SMTP$ = "smtp.gmail.com"
From$ = "sender@somewhere"
To$ = "recipient@elsewhere"
Subject$ = "Test of sending attachments"
ReplyTo$ = "reallyme@myaddress"
Plain$ = "This is a test of sending an HTML email."
HTML$ = "" + \
\ "This is a test of sending an HTML email." + \
\ ""
Attach$ = """C:\Program Files\BBC BASIC for Windows\readme.txt"""
PROCsendmailhtmlattach(SMTP$,From$,To$,"","",Subject$,ReplyTo$,Plain$,HTML$,Attach$)
The calling program should first check that the attached file(s) actually exist, because if not **PROCattach()** will abort with an error and not terminate the SMTP transaction; this could leave the server 'in limbo'. **Note that if an attached file path contains spaces or punctuation characters you must enclose it in quotes**.\\ \\ You should not assume that the receiving email client can necessarily render HTML, therefore ideally you should always include a **plain-text** message body as well as an **HTML** message body.\\ \\ Here is **PROCsendmailhtmlattach()**; like **PROCsendmail()** it cannot be used if authentication is required so in practice that probably means that your ISP's SMTP server must be used:\\
DEF PROCsendmailhtmlattach(smtp$,from$,rcpt$,cc$,bcc$,subject$,replyto$,plain$,html$,attach$)
LOCAL D%, S%, skt%, comma%, reply$, file$
DIM D% LOCAL 31, S% LOCAL 15
SYS "GetLocalTime", S%
SYS "GetDateFormat", 0, 0, S%, "ddd, dd MMM yyyy ", D%, 18
SYS "GetTimeFormat", 0, 0, S%, "HH:mm:ss +0000", D%+17, 15
D%?31 = 13
PROC_initsockets
skt% = FN_tcpconnect(smtp$,"mail")
IF skt% <= 0 skt% = FN_tcpconnect(smtp$,"25")
IF skt% <= 0 ERROR 100, "Failed to connect to mail server"
IF FN_readlinesocket(skt%, 1000, reply$)
WHILE FN_readlinesocket(skt%, 10, reply$) > 0 : ENDWHILE
PROCsend(skt%,"HELO "+FN_gethostname)
PROCmail(skt%,"MAIL FROM: ",from$)
IF rcpt$<>"" PROClist(skt%,rcpt$)
IF cc$<>"" PROClist(skt%,cc$)
IF bcc$<>"" PROClist(skt%,bcc$)
PROCsend(skt%, "DATA")
IF FN_writelinesocket(skt%, "Date: "+$D%)
IF FN_writelinesocket(skt%, "From: "+from$)
IF FN_writelinesocket(skt%, "To: "+rcpt$)
IF cc$<>"" IF FN_writelinesocket(skt%, "Cc: "+cc$)
IF subject$<>"" IF FN_writelinesocket(skt%, "Subject: "+subject$)
IF replyto$<>"" IF FN_writelinesocket(skt%, "Reply-To: "+replyto$)
IF FN_writelinesocket(skt%, "MIME-Version: 1.0")
IF attach$<>"" THEN
IF FN_writelinesocket(skt%, "Content-Type: multipart/mixed; boundary=""BB4Wsep""")
IF FN_writelinesocket(skt%, "")
IF FN_writelinesocket(skt%, "--BB4Wsep")
ENDIF
IF plain$<>"" IF html$<>"" THEN
IF FN_writelinesocket(skt%, "Content-Type: multipart/alternative; boundary=""BB4Wsep2""")
IF FN_writelinesocket(skt%, "")
IF FN_writelinesocket(skt%, "--BB4Wsep2")
ENDIF
IF plain$<>"" THEN
IF FN_writelinesocket(skt%, "Content-Type: text/plain")
IF FN_writelinesocket(skt%, "Content-Transfer-Encoding: 7bit")
IF FN_writelinesocket(skt%, "")
IF FN_writelinesocket(skt%, plain$)
ENDIF
IF plain$<>"" IF html$<>"" THEN
IF FN_writelinesocket(skt%, "--BB4Wsep2")
ENDIF
IF html$<>"" THEN
IF FN_writelinesocket(skt%, "Content-Type: text/html")
IF FN_writelinesocket(skt%, "Content-Transfer-Encoding: 7bit")
IF FN_writelinesocket(skt%, "")
IF FN_writelinesocket(skt%, html$)
ENDIF
IF plain$<>"" IF html$<>"" THEN
IF FN_writelinesocket(skt%, "--BB4Wsep2--")
ENDIF
IF attach$<>"" THEN
REPEAT
WHILE ASCattach$=32 attach$ = MID$(attach$,2) : ENDWHILE
IF ASCattach$=34 THEN
file$ = EVAL(attach$)
comma% = INSTR(attach$, ",", LENfile$)
ELSE
comma% = INSTR(attach$, ",")
IF comma% file$ = LEFT$(attach$, comma%-1) ELSE file$ = attach$
ENDIF
PROCattach(skt%, file$)
attach$ = MID$(attach$, comma%+1)
UNTIL comma%=0
IF FN_writelinesocket(skt%, "--BB4Wsep--")
ENDIF
IF FN_writelinesocket(skt%, ".")
PROCsend(skt%,"QUIT")
PROC_exitsockets
ENDPROC
DEF PROClist(skt%,list$)
LOCAL comma%
REPEAT
WHILE ASClist$=32 list$=MID$(list$,2):ENDWHILE
comma% = INSTR(list$,",")
IF comma% THEN
PROCmail(skt%,"RCPT TO: ",LEFT$(list$,comma%-1))
list$ = MID$(list$,comma%+1)
ELSE
PROCmail(skt%,"RCPT TO: ",list$)
ENDIF
UNTIL comma% = 0
ENDPROC
DEF PROCmail(skt%,cmd$,mail$)
LOCAL I%,J%
I% = INSTR(mail$,"<")
J% = INSTR(mail$,">",I%)
IF I% IF J% THEN
PROCsend(skt%, cmd$+MID$(mail$,I%,J%-I%+1))
ELSE
PROCsend(skt%, cmd$+"<"+mail$+">")
ENDIF
ENDPROC
DEF PROCsend(skt%,cmd$)
LOCAL reply$
IF FN_writelinesocket(skt%,cmd$) < 0 THEN
ERROR 100, "Send failed"
ENDIF
IF FN_readlinesocket(skt%, 200, reply$)
WHILE FN_readlinesocket(skt%, 10, reply$) > 0 : ENDWHILE
ENDPROC
DEF PROCattach(skt%,file$)
LOCAL D%, F%, I%, L%, N%, A$, B$
B$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
F% = OPENIN(file$)
IF F%=0 ERROR 100, "Failed to open attached file " + file$
REPEAT
D% = INSTR(file$, "\")
IF D%=0 D% = INSTR(file$, "/")
IF D% file$ = MID$(file$, D%+1)
UNTIL D%=0
IF FN_writelinesocket(skt%, "")
IF FN_writelinesocket(skt%, "--BB4Wsep")
IF FN_writelinesocket(skt%, "Content-Type: application/octet-stream")
IF FN_writelinesocket(skt%, "Content-Disposition: attachment; filename="+file$)
IF FN_writelinesocket(skt%, "Content-Transfer-Encoding: base64")
IF FN_writelinesocket(skt%, "")
L% = EXT#F%
WHILE NOT EOF#F%
N% = L% - PTR#F%
D% = BGET#F% << 16 OR BGET#F% << 8 OR BGET#F%
FOR I% = 1 TO 4 : A$ += MID$(B$,(D% >>> 18)+1,1) : D% = D% << 6 AND &FFFFFF : NEXT
IF N%=1 RIGHT$(A$,2) = "==" ELSE IF N%=2 RIGHT$(A$) = "="
IF LENA$>=72 IF FN_writelinesocket(skt%,A$)=0 A$ = ""
ENDWHILE
IF A$<>"" IF FN_writelinesocket(skt%, A$)
CLOSE #F%
ENDPROC