用4gl写的发送邮件程序,虽然说系统有标准的javamail。
应该是不用导入任何jar的,方法是用socket发送,虽然不常用,但有一些SMTP协议和编码的细节可以看看 IMPORT os IMPORT util IMPORT XML IMPORT JAVA java.lang.String IMPORT JAVA java.lang.Byte IMPORT JAVA java.net.URLEncoder IMPORT JAVA java.net.Socket IMPORT JAVA java.io.OutputStream IMPORT JAVA java.io.PrintWriter IMPORT JAVA java.io.BufferedReader IMPORT JAVA java.io.InputStreamReader IMPORT JAVA java.lang.StringBuffer IMPORT JAVA java.lang.Object IMPORT JAVA java.security.MessageDigest IMPORT JAVA java.lang.Integer IMPORT JAVA java.lang.Boolean IMPORT JAVA javax.net.ssl.SSLSocketFactory IMPORT JAVA java.nio.charset.Charset IMPORT JAVA org.apache.commons.codec.binary.Base64 IMPORT JAVA java.lang.System DATABASE ds GLOBALS "../../../tiptop/config/top.global" DEFINE g_Mail_Host STRING #发件服务器地址 DEFINE g_mail_Port INT #端口 DEFINE g_mail_User STRING #用户名 base64编码 DEFINE g_mail_Password STRING #密码 base64编码 DEFINE g_mail_From STRING #发件人邮箱 DEFINE g_mail_To STRING #收件人邮箱 DEFINE g_mail_To_Arr DYNAMIC ARRAY OF RECORD #收件人邮箱 to STRING END RECORD DEFINE g_mail_Cc STRING #收件人邮箱 抄送 DEFINE g_mail_Cc_Arr DYNAMIC ARRAY OF RECORD #收件人邮箱 抄送 cc STRING END RECORD DEFINE g_mail_Bcc STRING #收件人邮箱 密送 DEFINE g_mail_Bcc_Arr DYNAMIC ARRAY OF RECORD #收件人邮箱 密送 bcc STRING END RECORD DEFINE g_mail_Subject STRING #邮件主题 base64编码 DEFINE g_mail_Date STRING #时间 DEFINE g_mail_Content STRING #邮件内容 DEFINE g_mail_Attachment_Arr DYNAMIC ARRAY OF RECORD #邮件附件 dirname STRING, #附件名 attachment STRING #附件base64编码 END RECORD DEFINE g_charset STRING DEFINE g_msg STRING ###################################################### ###################################################### FUNCTION aws_send_mail() WHENEVER ERROR CONTINUE CALL aws_send_mail_Init() CALL aws_send_mail_SetHost("smtp.mxhichina.com") #设置发件服务器地址 CALL aws_send_mail_SetPort(465) #设置端口 CALL aws_send_mail_SetUser("01@test.com") #设置登录用户名 CALL aws_send_mail_SetPassword("111111") #设置登录密码 CALL aws_send_mail_SetFrom("01@test.com") #设置发件邮箱 CALL aws_send_mail_SetTo("02@test.com;03@test.com") #设置收件邮箱 多个用 ; 分隔 CALL aws_send_mail_SetCc("04@test.com;05@test.com") #设置抄送邮箱 多个用 ; 分隔 CALL aws_send_mail_SetBcc("06@test.com") #设置密送邮箱 多个用 ; 分隔 CALL aws_send_mail_SetSubject("测试邮件主题") #设置邮件主题 CALL aws_send_mail_SetDate() #设置日期时间 CALL aws_send_mail_SetContent("测试邮件内容") #设置邮件正文内容 CALL aws_send_mail_AddAttachment("/u1/toptest/topcust/coo/4gl/test.rar") #增加附件 CALL aws_send_mail_AddAttachment("/u1/toptest/topcust/coo/4gl/test3.rar") #增加附件 CALL aws_send_mail_Send() RETURNING g_msg #发送 IF g_success = 'N' THEN CALL cl_err('邮件发送失败!'||g_msg,'!',1) ELSE CALL cl_err('邮件发送成功!','!',1) END IF END FUNCTION FUNCTION aws_send_mail_Init() #初始化 LET g_msg = NULL LET g_Mail_Host = NULL LET g_mail_Port = NULL LET g_mail_User = NULL LET g_mail_Password = NULL LET g_mail_From = NULL LET g_mail_To = NULL CALL g_mail_To_Arr.clear() LET g_mail_Cc = NULL CALL g_mail_Cc_Arr.clear() LET g_mail_Bcc = NULL CALL g_mail_Bcc_Arr.clear() LET g_mail_Subject = NULL LET g_mail_Date = NULL LET g_mail_Content = NULL CALL g_mail_Attachment_Arr.clear() LET g_charset = java.nio.charset.Charset.defaultCharset().name() #字符集格式 IF cl_null(g_charset) THEN LET g_charset = 'UTF-8' END IF END FUNCTION FUNCTION aws_send_mail_Send() DEFINE boundary STRING DEFINE boundaryNextPart STRING DEFINE ls_str STRING DEFINE i INT DEFINE stmp_str java.lang.String DEFINE line_end java.lang.String DEFINE ls_line java.lang.String DEFINE lb_str base.StringBuffer DEFINE lj_socket java.net.Socket DEFINE lj_os java.io.OutputStream DEFINE lj_out java.io.PrintWriter DEFINE lj_isr java.io.InputStreamReader DEFINE lj_in java.io.BufferedReader LET g_success = 'Y' LET line_end = '\r\n' #换行符 LET boundary = "--=_NextPart_" , java.lang.System.currentTimeMillis() #时间戳 LET boundary = cl_replace_str(boundary,' ','') #分隔 LET boundaryNextPart = "--" , boundary # LET lj_socket = Socket.create("smtp.mxhichina.com",25) #默认25端口 LET lj_socket = SSLSocketFactory.getDefault().createSocket(g_Mail_Host, g_Mail_Port) #SSL 465端口 CALL lj_socket.setSoTimeout(5000) #设置5秒读取超时 LET lj_os = lj_socket.getOutputStream() #取得串流 LET lj_out = PrintWriter.create(lj_os, true) LET lj_isr = InputStreamReader.create(lj_socket.getInputStream()) LET lj_in = BufferedReader.create(lj_isr) WHILE TRUE #握手 CALL lj_out.flush() #刷新输出流 LET stmp_str = "HELO " LET stmp_str = stmp_str.concat(g_Mail_Host) #发件邮箱服务器 CALL lj_out.write(stmp_str.concat(line_end)) #送出request #握手 LET ls_line = lj_in.readLine() #读取response #220 smtp.aliyun-inc.com MX AliMail Server IF cl_null(ls_line) OR ls_line.indexOf("220") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #登录 CALL lj_out.flush() #刷新输出流 LET stmp_str = "AUTH LOGIN" CALL lj_out.write(stmp_str.concat(line_end)) #送出request #登录 LET ls_line = lj_in.readLine() #读取response #250 OK IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #输入用户名 CALL lj_out.flush() #刷新输出流 LET stmp_str = g_mail_User CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入用户名(base64) LET ls_line = lj_in.readLine() #读取response #334 dXNlcm5hbWU6 IF cl_null(ls_line) OR ls_line.indexOf("334") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #输入密码 CALL lj_out.flush() #刷新输出流 LET stmp_str = g_mail_Password CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入密码(base64) LET ls_line = lj_in.readLine() #读取response #334 UGFzc3dvcmQ6 IF cl_null(ls_line) OR ls_line.indexOf("334") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #输入发件人邮箱地址 CALL lj_out.flush() #刷新输出流 LET stmp_str = "MAIL FROM:" || g_mail_From #发件人邮箱地址 CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入发件人邮箱地址 LET ls_line = lj_in.readLine() #读取response #235 Authentication successful IF cl_null(ls_line) OR ls_line.indexOf("235") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #输入收件人邮箱地址 FOR i = 1 TO g_mail_To_Arr.getLength() CALL lj_out.flush() #刷新输出流 LET stmp_str = "RCPT TO:" || g_mail_To_Arr.to #收件人邮箱地址 包括发送、抄送、密送 CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入收件人邮箱地址 LET ls_line = lj_in.readLine() #读取response #250 Mail Ok IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT FOR END IF END FOR IF g_success = 'N' THEN EXIT WHILE END IF FOR i = 1 TO g_mail_Cc_Arr.getLength() CALL lj_out.flush() #刷新输出流 LET stmp_str = "RCPT TO:" || g_mail_Cc_Arr.Cc #收件人邮箱地址 包括发送、抄送、密送 CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入收件人邮箱地址 LET ls_line = lj_in.readLine() #读取response #250 Mail Ok IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT FOR END IF END FOR IF g_success = 'N' THEN EXIT WHILE END IF FOR i = 1 TO g_mail_Bcc_Arr.getLength() CALL lj_out.flush() #刷新输出流 LET stmp_str = "RCPT TO:" || g_mail_Bcc_Arr.bcc #收件人邮箱地址 包括发送、抄送、密送 CALL lj_out.write(stmp_str.concat(line_end)) #送出request #输入收件人邮箱地址 LET ls_line = lj_in.readLine() #读取response #250 Mail Ok IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT FOR END IF END FOR IF g_success = 'N' THEN EXIT WHILE END IF #开始输入邮件 CALL lj_out.flush() #刷新输出流 LET stmp_str = "DATA" #开始输入邮件 CALL lj_out.write(stmp_str.concat(line_end)) #送出request LET ls_line = lj_in.readLine() #读取response #250 IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #设置邮件头信息 LET lb_str = base.StringBuffer.create() LET ls_str = "From: " , g_mail_From , line_end CALL lb_str.append(ls_str) #发件人 LET ls_str = "To: " , g_mail_To , line_end CALL lb_str.append(ls_str) #收件人 LET ls_str = "Cc: " , g_mail_Cc , line_end CALL lb_str.append(ls_str) #抄送 # LET ls_str = "Bcc: " , g_mail_Bcc , line_end #在这里邮件头加入Bcc密送邮箱会失去密送隐秘效果,只在前面 RCPT TO 加上即可 # CALL lb_str.append(ls_str) #密送 LET ls_str = "Subject: " , g_mail_Subject , line_end CALL lb_str.append(ls_str) #邮件主题 LET ls_str = "Date: " , g_mail_Date , line_end CALL lb_str.append(ls_str) #时间 yyyy-MM-dd HH:mm:ss LET ls_str = "Content-Type: " , "multipart/alternative" , ";" CALL lb_str.append(ls_str) LET ls_str = 'boundary="' , boundary , '"' , line_end CALL lb_str.append(ls_str) LET ls_str = "This is a multi-part message in MIME format." , line_end CALL lb_str.append(ls_str) CALL lb_str.append(line_end) #邮件正文 LET ls_str = boundaryNextPart , line_end CALL lb_str.append(ls_str) LET ls_str = "Content-Type: text/plain;" , 'charset="' , g_charset , '"' , line_end CALL lb_str.append(ls_str) LET ls_str = "Content-Transfer-Encoding: " , "base64" , line_end CALL lb_str.append(ls_str) CALL lb_str.append(line_end) LET ls_str = g_mail_Content , line_end CALL lb_str.append(ls_str) #邮件附件 FOR i = 1 TO g_Mail_Attachment_Arr.getLength() LET ls_str = boundaryNextPart , line_end CALL lb_str.append(ls_str) LET ls_str = 'Content-Type: ' , aws_send_mail_GetContenttype(g_Mail_Attachment_Arr.dirname) , ";" , 'name="=?' , g_charset , '?B?' , g_Mail_Attachment_Arr.dirname , '?="' , line_end CALL lb_str.append(ls_str) LET ls_str = "Content-Transfer-Encoding: " , "base64" , line_end CALL lb_str.append(ls_str) LET ls_str = 'Content-Disposition: attachment' , ";" , 'filename="=?' , g_charset , '?B?' , g_Mail_Attachment_Arr.dirname , '?="' , line_end CALL lb_str.append(ls_str) CALL lb_str.append(line_end) LET ls_str = g_Mail_Attachment_Arr.attachment , line_end CALL lb_str.append(ls_str) END FOR LET ls_str = line_end , "." , line_end CALL lb_str.append(ls_str) #发送 CALL lj_out.flush() #刷新输出流 LET stmp_str = lb_str.toString() CALL lj_out.write(stmp_str) #送出request LET ls_line = lj_in.readLine() #读取response #354 IF cl_null(ls_line) OR ls_line.indexOf("354") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line EXIT WHILE END IF #退出 CALL lj_out.flush() #刷新输出流 LET stmp_str = "QUIT" #退出 CALL lj_out.write(stmp_str.concat(line_end)) #送出request LET ls_line = lj_in.readLine() #读取response #250 IF cl_null(ls_line) OR ls_line.indexOf("250") < 0 THEN #判断回传码 LET g_success = 'N' LET g_msg = ls_line CALL lj_out.write(stmp_str.concat(line_end)) #失败再退出一遍 EXIT WHILE END IF EXIT WHILE END WHILE #关闭这三个对象Socket PrintWriter BufferedReader CALL lj_socket.close() CALL lj_in.close() CALL lj_out.close() RETURN g_msg END FUNCTION #字符串base64加密 FUNCTION aws_send_mail_base64_Encode_String(p_str,p_charset) DEFINE p_str STRING DEFINE p_charset STRING DEFINE l_str java.lang.String DEFINE lo_base64 org.apache.commons.codec.binary.Base64 DEFINE ls_enc STRING LET l_str = String.create(p_str) LET lo_base64 = Base64.create() IF (p_charset IS NULL) OR p_charset.equals("") THEN LET p_charset = "UTF-8" END IF LET ls_enc = lo_base64.encodeToString(l_str.getBytes(p_charset)) #base64 加密 RETURN ls_enc END FUNCTION #读取文件成base64 用linux命令方式 FUNCTION aws_send_mail_base64_Encode_File(p_path) DEFINE p_path STRING DEFINE l_path STRING DEFINE l_cmd STRING DEFINE l_name STRING DEFINE code INT DEFINE result STRING DEFINE ch base.Channel WHENEVER ERROR CONTINUE IF NOT os.Path.exists(p_path) THEN RETURN '' END IF LET l_path = '/u1/toptest/topcust/cxm/4gl' #一个默认存临时文件的路径 LET l_name = '/u1/toptest/topcust/cxm/4gl/base64中间文件.txt' LET l_cmd = "base64 '" || p_path || "' > '" || l_name || "' " RUN l_cmd RETURNING code IF code THEN RETURN '' END IF IF NOT os.Path.exists(l_name) THEN RETURN '' END IF #读取临时文件 LET ch = base.channel.create() CALL ch.openFile(l_name,"r") IF STATUS THEN RUN "rm '" || l_name || "'" RETURN '' END IF WHILE NOT ch.isEof() LET result = result,ch.readLine() IF NOT ch.isEof() THEN LET result = result,"\r\n" END IF END WHILE CALL ch.close() RUN "rm '" || l_name || "'" RETURN result END FUNCTION FUNCTION aws_send_mail_GetContenttype(p_path) DEFINE p_path STRING DEFINE l_dirname LIKE type_file.chr1000 DEFINE l_contenttype STRING SELECT SUBSTR(l_dirname, INSTR(l_dirname, '.', -1) + 1) INTO l_dirname FROM dual CASE l_dirname WHEN 'xls' LET l_contenttype = "application/vnd.ms-excel" WHEN 'xlsx' LET l_contenttype = "application/vnd.ms-excel" WHEN 'xlsm' LET l_contenttype = "application/vnd.ms-excel" WHEN 'xlsb' LET l_contenttype = "application/vnd.ms-excel" WHEN 'doc' LET l_contenttype = "application/msword" WHEN 'dot' LET l_contenttype = "application/msword" WHEN 'docx' LET l_contenttype = "application/msword" WHEN 'docm' LET l_contenttype = "application/msword" WHEN 'dotm' LET l_contenttype = "application/msword" END CASE IF cl_null(l_contenttype) THEN LET l_contenttype = "application/octet-stream" END IF RETURN l_contenttype END FUNCTION FUNCTION aws_send_mail_SetHost(p_host) DEFINE p_host STRING LET g_Mail_Host = p_host END FUNCTION FUNCTION aws_send_mail_SetPort(p_port) DEFINE p_port INT LET g_Mail_Port = p_port END FUNCTION FUNCTION aws_send_mail_SetUser(p_user) DEFINE p_user STRING LET g_Mail_User = aws_send_mail_base64_Encode_String(p_user,g_charset) #base64编码 END FUNCTION FUNCTION aws_send_mail_SetPassword(p_password) DEFINE p_password STRING LET g_Mail_Password = aws_send_mail_base64_Encode_String(p_password,g_charset) #base64编码 END FUNCTION FUNCTION aws_send_mail_SetFrom(p_from) DEFINE p_from STRING LET g_Mail_From = "<",p_from,">" END FUNCTION FUNCTION aws_send_mail_SetTo(p_to) DEFINE p_to STRING DEFINE l_to STRING DEFINE l_tok base.StringTokenizer DEFINE l_cnt INT DEFINE i INT IF cl_null(p_to) THEN RETURN END IF LET l_cnt = 0 LET l_tok = base.StringTokenizer.create(p_to,";") WHILE l_tok.hasMoreTokens() LET l_to = l_tok.nextToken() IF cl_null(l_to) THEN CONTINUE WHILE END IF LET l_cnt = l_cnt + 1 LET g_Mail_To_Arr[l_cnt].to = "<",l_to,">" END WHILE FOR i = 1 TO g_Mail_To_Arr.getLength() IF cl_null(g_Mail_To) THEN LET g_Mail_To = g_Mail_To_Arr.to ELSE LET g_Mail_To = g_Mail_To,";",g_Mail_To_Arr.to END IF END FOR END FUNCTION FUNCTION aws_send_mail_SetCc(p_cc) DEFINE p_cc STRING DEFINE l_cc STRING DEFINE l_tok base.StringTokenizer DEFINE l_cnt INT DEFINE i INT IF cl_null(p_cc) THEN RETURN END IF LET l_cnt = 0 LET l_tok = base.StringTokenizer.create(p_cc,";") WHILE l_tok.hasMoreTokens() LET l_cc = l_tok.nextToken() IF cl_null(l_cc) THEN CONTINUE WHILE END IF LET l_cnt = l_cnt + 1 LET g_Mail_Cc_Arr[l_cnt].cc = "<",l_cc,">" END WHILE FOR i = 1 TO g_Mail_Cc_Arr.getLength() IF cl_null(g_Mail_Cc) THEN LET g_Mail_Cc = g_Mail_Cc_Arr.cc ELSE LET g_Mail_Cc = g_Mail_Cc,";",g_Mail_Cc_Arr.cc END IF END FOR END FUNCTION FUNCTION aws_send_mail_SetBcc(p_bcc) DEFINE p_bcc STRING DEFINE l_bcc STRING DEFINE l_tok base.StringTokenizer DEFINE l_cnt INT DEFINE i INT IF cl_null(p_bcc) THEN RETURN END IF LET l_cnt = 0 LET l_tok = base.StringTokenizer.create(p_bcc,";") WHILE l_tok.hasMoreTokens() LET l_bcc = l_tok.nextToken() IF cl_null(l_bcc) THEN CONTINUE WHILE END IF LET l_cnt = l_cnt + 1 LET g_Mail_Bcc_Arr[l_cnt].bcc = "<",l_bcc,">" END WHILE FOR i = 1 TO g_Mail_Bcc_Arr.getLength() IF cl_null(g_Mail_Bcc) THEN LET g_Mail_Bcc = g_Mail_Bcc_Arr.bcc ELSE LET g_Mail_Bcc = g_Mail_Bcc,";",g_Mail_Bcc_Arr.bcc END IF END FOR END FUNCTION FUNCTION aws_send_mail_SetSubject(p_subject) DEFINE p_subject STRING LET g_Mail_Subject = p_subject END FUNCTION FUNCTION aws_send_mail_SetDate() DEFINE l_date LIKE type_file.chr100 SELECT TO_CHAR(sysdate,'YYYY-MM-DD HH:MI:SS') INTO l_date FROM dual LET g_Mail_Date = l_date END FUNCTION FUNCTION aws_send_mail_SetContent(p_content) DEFINE p_content STRING LET g_Mail_Content = aws_send_mail_base64_Encode_String(p_content,g_charset) #base64编码 END FUNCTION FUNCTION aws_send_mail_AddAttachment(p_dirpath) DEFINE p_dirpath STRING DEFINE i INT IF cl_null(p_dirpath) THEN RETURN END IF IF NOT os.Path.exists(p_dirpath) THEN RETURN END IF IF g_Mail_Attachment_Arr.getLength() <= 0 THEN LET i = 1 ELSE LET i = g_Mail_Attachment_Arr.getLength() + 1 END IF LET g_Mail_Attachment_Arr.dirname = aws_send_mail_base64_Encode_String(os.Path.basename(p_dirpath),g_charset) #文件名base64编码 os.Path.basename()取出路径文件名 LET g_Mail_Attachment_Arr.attachment = aws_send_mail_base64_Encode_File(p_dirpath) #读取路径文件成base64编码 END FUNCTION |
|