mail send a mail message (attachments optional) to a list of addresses MAIL(TO, SUBJECT, MESSAGE, ATTACHMENTS) TO: List of users to receive mail. A string if single address, or a cell-array of strings for multiple receipients SUBJECT: The subject line of the message MESSAGE: Either a string containing the message to send. ATTACHMENTS: Optional cell-array of files to attach and send along with the message Example: sendmail('user@otherdomain.com','Test subject','Test message', ... {'directory/attach1.html','attach2.doc'});
0001 % mail send a mail message (attachments optional) to a list of addresses 0002 % 0003 % MAIL(TO, SUBJECT, MESSAGE, ATTACHMENTS) 0004 % 0005 % TO: List of users to receive mail. A string if single address, or a 0006 % cell-array of strings for multiple receipients 0007 % SUBJECT: The subject line of the message 0008 % MESSAGE: Either a string containing the message to send. 0009 % ATTACHMENTS: Optional cell-array of files to attach and send along with the 0010 % message 0011 % 0012 % Example: 0013 % 0014 % sendmail('user@otherdomain.com','Test subject','Test message', ... 0015 % {'directory/attach1.html','attach2.doc'}); 0016 0017 % Use the SMTP protocol directly. Connect to the SMTP port on the given 0018 % mail server, and chat away. Use MIME encoding to ship a multipart/mixed 0019 % message. 0020 % 0021 % RFC 821 lists the SMTP status codes. Multiple copies of that document 0022 % exist on the Internet. See http://www.landfield.com/rfcs/rfc821.html 0023 % for one example. 0024 0025 % Peter Webb, Aug. 2000 0026 % Matthew J. Simoneau, Nov. 2001 0027 % Copyright 1984-2002 The MathWorks, Inc. 0028 % $Revision: 1.1 $ $Date: 2004/05/12 18:49:13 $ 0029 0030 function mail(server, port, from, to, subject, message, attachments) 0031 0032 global base64Map 0033 0034 %error(nargchk(2,4,nargin)); 0035 0036 % % Supply defaults 0037 % if (nargin < 6) 0038 % message='';, 0039 % end; 0040 % if (nargin < 7) 0041 % attachments=[]; 0042 % end; 0043 0044 % Determine SERVER 0045 % server=getpref('Internet','SMTP_Server',''); 0046 % if isempty(server) & ispc 0047 % try 0048 % defaultMailAccount=winqueryreg('HKEY_CURRENT_USER', ... 0049 % 'Software\Microsoft\Internet Account Manager', ... 0050 % 'Default Mail Account'); 0051 % defaultMailAccountRegistry = ... 0052 % ['Software\Microsoft\Internet Account Manager\Accounts\' ... 0053 % defaultMailAccount]; 0054 % server=winqueryreg('HKEY_CURRENT_USER', defaultMailAccountRegistry, ... 0055 % 'SMTP Server'); 0056 % catch 0057 % end 0058 % end 0059 % if isempty(server) 0060 % server = getenv('mailhost'); 0061 % end 0062 % if isempty(server) 0063 % error(sprintf('%s\n%s', ... 0064 % 'Could not determine SMTP server. You can set one like this: ', ... 0065 % 'setpref(''Internet'',''SMTP_Server'',''myserver.myhost.com'');')) 0066 % end 0067 0068 % Determine FROM 0069 % from=getpref('Internet','E_mail',''); 0070 % if isempty(from) & ispc 0071 % try 0072 % from=winqueryreg('HKEY_CURRENT_USER', defaultMailAccountRegistry, ... 0073 % 'SMTP Email Address'); 0074 % catch 0075 % end 0076 % end 0077 % if isempty(from) 0078 % from = getenv('LOGNAME'); 0079 % end 0080 % if isempty(from) 0081 % error(sprintf('%s\n%s', ... 0082 % 'Could not determine FROM address. You can set one like this: ', ... 0083 % 'setpref(''Internet'',''E_mail'',''username'');')) 0084 % end 0085 0086 % Everyone uses this port, right? 0087 % port = 25; 0088 0089 % Set up the base 64 conversion map 0090 % A:Z a:z 0:9 + / 0091 base64Map = char([65:90 97:122 48:57 '+' '/' '=']); 0092 0093 % Connect to given SMTP server 0094 try 0095 mail = java.net.Socket(server, port); 0096 catch 0097 error(sprintf('Could not establish connection with %s on port %i.', ... 0098 server,port)); 0099 end 0100 0101 % Get the output and input streams from the socket connection 0102 out = java.io.DataOutputStream(getOutputStream(mail)); 0103 in = java.io.DataInputStream(getInputStream(mail)); 0104 0105 % Message acknowledging the SMTP server is alive 0106 [status, code] = okSMTP(readmsg(in)); 0107 if status == 0, error('No answer from SMTP server.'), end 0108 0109 % The boundary to be used between the parts of the message 0110 boundary = '----=_X_X_sendmail.m_X_X_'; 0111 0112 % Regular SMTP protocol. These lines must be sent in this order. 0113 % Start a session 0114 sendSMTP(out, in, 'HELO mailman', 1); 0115 0116 % Set sender 0117 sendSMTP(out, in, ['MAIL FROM: ' from], 1); 0118 0119 % Set recipients 0120 if iscell(to) 0121 for i=1:length(to)' 0122 sendSMTP(out, in, ['RCPT TO: ' to{i}], 1); 0123 end 0124 else 0125 sendSMTP(out, in, ['RCPT TO: ' to], 1); 0126 end 0127 0128 % Send the body of the message 0129 sendSMTP(out, in, 'DATA', 1); 0130 sendSMTP(out, in, ['Subject: ' subject], 0); 0131 0132 % Here, it gets interesting. Send the Mime-Version header because we're 0133 % using MIME encoding 0134 sendSMTP(out, in, 'Mime-Version: 1.0', 0); 0135 0136 % If there are attachments, this is a multipart message 0137 if length(attachments) > 0 0138 sendSMTP(out, in, ... 0139 ['Content-Type: multipart/mixed; boundary="' boundary '"'], 0); 0140 sendSMTP(out, in, ['--' boundary], 0); 0141 end 0142 0143 % Start boundary for the first (text) section 0144 sendSMTP(out, in, ['Content-Type: text/plain; charset=us-ascii' 13 10], 0); 0145 0146 if ~isempty(message) 0147 sendText(message, in, out); 0148 end 0149 0150 % Loop over the attachments, sending each in its own section 0151 if length(attachments) > 0 0152 for i=1:length(attachments) 0153 % Start boundary for the next attachment 0154 sendSMTP(out, in, [13 10 '--' boundary], 0); 0155 % It's very important that there be a blank line between these Content-* 0156 % statements and the start of the attachment data 0157 sendSMTP(out, in, ['Content-Type: application/octet-stream'], 0); 0158 sendSMTP(out, in, 'Content-transfer-encoding: base64', 0); 0159 % Remove the directory, if any, from the attachement name. 0160 [fileDir,fileName,fileExt]=fileparts(attachments{i}); 0161 sendSMTP(out, in, ['Content-Disposition: attachment; filename=' fileName fileExt 13 10], 0); 0162 % Send the attachment data 0163 sendBinaryFile(attachments{i}, in, out); 0164 end 0165 % End boundary for the message 0166 sendSMTP(out, in, [13 10 '--' boundary '--'], 0); 0167 end 0168 0169 % Indicate we're done with the data section of the message 0170 sendSMTP(out, in, '.', 1); 0171 0172 % Terminate the SMTP session 0173 sendSMTP(out, in, 'QUIT', 1); 0174 0175 % Close the mail socket 0176 close(mail); 0177 0178 %=============================================================================== 0179 function sendSMTP(out, in, msg, rflag) 0180 % Send a text along an SMTP connection 0181 0182 % Send the text 0183 msg = java.lang.String([msg 13 10]); 0184 writeBytes(out, msg); 0185 0186 % Read and check the response, if the rflag is non-zero 0187 if rflag 0188 [smtpStatus, smtpCode] = okSMTP(readmsg(in)); 0189 if smtpStatus == 0, error('SMTP error');, end 0190 else 0191 status = 1; 0192 code = 0; 0193 end 0194 0195 %=============================================================================== 0196 function sendText(msg_text, in, out) 0197 % Send a block of text (break into 75 character lines) along the SMTP 0198 % connection 0199 spacing = 75; 0200 0201 msg_text=[msg_text char(10)]; 0202 cr = find(double(msg_text) == 10); 0203 numstr = length(cr); 0204 cr = [0 cr]; 0205 0206 for i = 1:numstr 0207 text = msg_text(cr(i) + 1:cr(i+1) - 1); 0208 start = 1; 0209 current = 0; 0210 len = length(text); 0211 0212 % While we aren't at the end of the text string 0213 while current < len 0214 % Advance by one line length 0215 current = current + min(spacing, len - start + 1); 0216 % Look for the nearest space "behind" the current position 0217 if current < len 0218 while text(current) ~= ' ' & current > start 0219 current = current - 1; 0220 end 0221 end 0222 % If there weren't any spaces, advance to the end of the line 0223 if current == start 0224 current = current + min(spacing, len); 0225 end 0226 0227 % Send this line of text 0228 sendSMTP(out, in, text(start:current), 0); 0229 start = current+1; 0230 end 0231 0232 end 0233 0234 %=============================================================================== 0235 function b64 = base64(data) 0236 % Convert 24 bits of base 256 data into 32 bits of base 64 data 0237 global base64Map 0238 sixbits = 63; 0239 one = 18; 0240 two = 12; 0241 three = 6; 0242 four = 0; 0243 0244 % Break the data into four 6-bit letters 0245 b64(1) = bitshift(bitand(data, bitshift(sixbits, one)), -one); 0246 b64(2) = bitshift(bitand(data, bitshift(sixbits, two)), -two); 0247 b64(3) = bitshift(bitand(data, bitshift(sixbits, three)), -three); 0248 b64(4) = bitshift(bitand(data, bitshift(sixbits, four)), -four); 0249 0250 b64 = base64Map(b64+1); 0251 0252 %=============================================================================== 0253 function encoded = encode64(data) 0254 % Encode a string of bytes into base64, as defined by RFC 2045 0255 count = 1; 0256 left = mod(length(data),3); 0257 len = length(data)-left; 0258 for i=1:3:len 0259 group = bitshift(data(i),16) + bitshift(data(i+1),8) + data(i+2); 0260 encoded(count:count+3) = base64(group); 0261 count = count+4; 0262 end 0263 if left ~= 0 0264 group = bitshift(data(len+1),16); 0265 padstr = '=='; 0266 if left == 2 0267 group = group + bitshift(data(len+2),8); 0268 padstr = '='; 0269 end 0270 b64 = base64(group); 0271 encoded(count:count+left) = b64(1:left+1); 0272 count=count+left+1; 0273 encoded(count:count+length(padstr)-1) = padstr; 0274 end 0275 0276 %=============================================================================== 0277 function sendBinaryFile(name, in, out) 0278 % Send a binary file. Encode into base64. Send no more than 76 characters 0279 % at a time. 0280 maxc = 57; 0281 fid=fopen(name, 'r'); 0282 while 1 0283 [line, count] = fread(fid, maxc, 'uchar'); 0284 if count == 0, break, end 0285 sendSMTP(out, in, encode64(line), 0); 0286 end 0287 fclose(fid); 0288 0289 %=============================================================================== 0290 function msg=readmsg(in) 0291 msg=char(readLine(in)); 0292 % Read (using Java) a line of bytes from the SMTP connection. Block until 0293 % we get something to read. 0294 0295 0296 %=============================================================================== 0297 function [status, code] = okSMTP(message) 0298 % Check the code returned by the SMTP server. The code is the first 3 0299 % characters of the response. The first digit of the command determines 0300 % success or failure: 0301 % 0302 % 2 : Command succeeded 0303 % 3 : Success (informational message) 0304 % 4 : Transient error (try again) 0305 % 5 : Permanent error (fix commands before trying again) 0306 0307 code = message(1:3); 0308 switch code(1) 0309 case '2' 0310 status = 1; 0311 case '3' 0312 status = 1; 0313 case '4' 0314 status = 0; 0315 case '5' 0316 status = 0; 0317 otherwise 0318 status = 0; 0319 end