mail

PURPOSE ^

mail send a mail message (attachments optional) to a list of addresses

SYNOPSIS ^

function mail(server, port, from, to, subject, message, attachments)

DESCRIPTION ^

 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'});

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

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

Generated on Sun 15-Aug-2004 22:13:10 by m2html © 2003