/[classpath]/inetlib/source/gnu/inet/smtp/SMTPConnection.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/smtp/SMTPConnection.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by dog, Thu Oct 21 15:21:55 2004 UTC revision 1.19 by dog, Thu Nov 25 22:15:05 2004 UTC
# Line 1  Line 1 
1  /*  /*
2   * $Id$   * SMTPConnection.java
3   * Copyright (C) 2003 Chris Burdess <dog@gnu.org>   * Copyright (C) 2003 Chris Burdess <dog@gnu.org>
4   *   *
5   * This file is part of GNU inetlib, a library.   * This file is part of GNU inetlib, a library.
# Line 81  import gnu.inet.util.SaslPlain; Line 81  import gnu.inet.util.SaslPlain;
81   * This implements RFC 2821.   * This implements RFC 2821.
82   *   *
83   * @author <a href="mailto:dog@gnu.org">Chris Burdess</a>   * @author <a href="mailto:dog@gnu.org">Chris Burdess</a>
  * @version $Revision$ $Date$  
84   */   */
85  public class SMTPConnection  public class SMTPConnection
86  {  {
# Line 155  public class SMTPConnection Line 154  public class SMTPConnection
154     * port.     * port.
155     * @param host the server hostname     * @param host the server hostname
156     */     */
157    public SMTPConnection (String host) throws IOException    public SMTPConnection(String host)
158        throws IOException
159    {    {
160      this (host, DEFAULT_PORT);      this(host, DEFAULT_PORT);
161    }    }
162    
163    /**    /**
# Line 166  public class SMTPConnection Line 166  public class SMTPConnection
166     * @param host the server hostname     * @param host the server hostname
167     * @param port the port to connect to     * @param port the port to connect to
168     */     */
169    public SMTPConnection (String host, int port) throws IOException    public SMTPConnection(String host, int port)
170        throws IOException
171    {    {
172      this (host, port, 0, 0, false);      this(host, port, 0, 0, false);
173    }    }
174    
175    /**    /**
# Line 180  public class SMTPConnection Line 181  public class SMTPConnection
181     * @param timeout the I/O timeout in milliseconds     * @param timeout the I/O timeout in milliseconds
182     * @param debug whether to log progress     * @param debug whether to log progress
183     */     */
184    public SMTPConnection (String host, int port,    public SMTPConnection(String host, int port,
185                           int connectionTimeout, int timeout, boolean debug)                          int connectionTimeout, int timeout, boolean debug)
186      throws IOException      throws IOException
187    {    {
188      if (port <= 0)      if (port <= 0)
# Line 193  public class SMTPConnection Line 194  public class SMTPConnection
194      this.debug = debug;      this.debug = debug;
195            
196      // Initialise socket      // Initialise socket
197      socket = new Socket ();      socket = new Socket();
198      InetSocketAddress address = new InetSocketAddress (host, port);      InetSocketAddress address = new InetSocketAddress(host, port);
199      if (connectionTimeout > 0)      if (connectionTimeout > 0)
200        {        {
201          socket.connect (address, connectionTimeout);          socket.connect(address, connectionTimeout);
202        }        }
203      else      else
204        {        {
205          socket.connect (address);          socket.connect(address);
206        }        }
207      if (timeout > 0)      if (timeout > 0)
208        {        {
209          socket.setSoTimeout (timeout);          socket.setSoTimeout(timeout);
210        }        }
211            
212      // Initialise streams      // Initialise streams
213      InputStream in = socket.getInputStream ();      InputStream in = socket.getInputStream();
214      in = new BufferedInputStream (in);      in = new BufferedInputStream(in);
215      in = new CRLFInputStream (in);      in = new CRLFInputStream(in);
216      this.in = new LineInputStream (in);      this.in = new LineInputStream(in);
217      OutputStream out = socket.getOutputStream ();      OutputStream out = socket.getOutputStream();
218      out = new BufferedOutputStream (out);      out = new BufferedOutputStream(out);
219      this.out = new CRLFOutputStream (out);      this.out = new CRLFOutputStream(out);
220            
221      // Greeting      // Greeting
222      StringBuffer greetingBuffer = new StringBuffer ();      StringBuffer greetingBuffer = new StringBuffer();
223      boolean notFirst = false;      boolean notFirst = false;
224      do      do
225        {        {
226          if (getResponse () != READY)          if (getResponse() != READY)
227            {            {
228              throw new ProtocolException (response);              throw new ProtocolException(response);
229            }            }
230          if (notFirst)          if (notFirst)
231            {            {
232              greetingBuffer.append ('\n');              greetingBuffer.append('\n');
233            }            }
234          else          else
235            {            {
236              notFirst = true;              notFirst = true;
237            }            }
238          greetingBuffer.append (response);          greetingBuffer.append(response);
239                    
240        }        }
241      while (continuation);      while (continuation);
242      greeting = greetingBuffer.toString ();      greeting = greetingBuffer.toString();
243    }    }
244        
245    /**    /**
246     * Returns the server greeting message.     * Returns the server greeting message.
247     */     */
248    public String getGreeting ()    public String getGreeting()
249    {    {
250      return greeting;      return greeting;
251    }    }
# Line 252  public class SMTPConnection Line 253  public class SMTPConnection
253    /**    /**
254     * Returns the text of the last response received from the server.     * Returns the text of the last response received from the server.
255     */     */
256    public String getLastResponse ()    public String getLastResponse()
257    {    {
258      return response;      return response;
259    }    }
# Line 261  public class SMTPConnection Line 262  public class SMTPConnection
262    
263    /**    /**
264     * Execute a MAIL command.     * Execute a MAIL command.
265     * @param reversePath the source mailbox (from address)     * @param reversePath the source mailbox(from address)
266     * @param parameters optional ESMTP parameters     * @param parameters optional ESMTP parameters
267     * @return true if accepted, false otherwise     * @return true if accepted, false otherwise
268     */     */
269    public boolean mailFrom (String reversePath, ParameterList parameters)    public boolean mailFrom(String reversePath, ParameterList parameters)
270      throws IOException      throws IOException
271    {    {
272      StringBuffer command = new StringBuffer (MAIL_FROM);      StringBuffer command = new StringBuffer(MAIL_FROM);
273      command.append ('<');      command.append('<');
274      command.append (reversePath);      command.append(reversePath);
275      command.append ('>');      command.append('>');
276      if (parameters != null)      if (parameters != null)
277        {        {
278          command.append (SP);          command.append(SP);
279          command.append (parameters);          command.append(parameters);
280        }        }
281      send (command.toString ());      send(command.toString());
282      switch (getAllResponses ())      switch (getAllResponses())
283        {        {
284        case OK:        case OK:
285        case OK_NOT_LOCAL:        case OK_NOT_LOCAL:
# Line 291  public class SMTPConnection Line 292  public class SMTPConnection
292    
293    /**    /**
294     * Execute a RCPT command.     * Execute a RCPT command.
295     * @param forwardPath the forward-path (recipient address)     * @param forwardPath the forward-path(recipient address)
296     * @param parameters optional ESMTP parameters     * @param parameters optional ESMTP parameters
297     * @return true if successful, false otherwise     * @return true if successful, false otherwise
298     */     */
299    public boolean rcptTo (String forwardPath, ParameterList parameters)    public boolean rcptTo(String forwardPath, ParameterList parameters)
300      throws IOException      throws IOException
301    {    {
302      StringBuffer command = new StringBuffer (RCPT_TO);      StringBuffer command = new StringBuffer(RCPT_TO);
303      command.append ('<');      command.append('<');
304      command.append (forwardPath);      command.append(forwardPath);
305      command.append ('>');      command.append('>');
306      if (parameters != null)      if (parameters != null)
307        {        {
308          command.append (SP);          command.append(SP);
309          command.append (parameters);          command.append(parameters);
310        }        }
311      send (command.toString ());      send(command.toString());
312      switch (getAllResponses ())      switch (getAllResponses())
313        {        {
314        case OK:        case OK:
315        case OK_NOT_LOCAL:        case OK_NOT_LOCAL:
# Line 328  public class SMTPConnection Line 329  public class SMTPConnection
329     * must be called to complete the transfer and determine its success.     * must be called to complete the transfer and determine its success.
330     * @return a stream for writing messages to     * @return a stream for writing messages to
331     */     */
332    public OutputStream data () throws IOException    public OutputStream data()
333        throws IOException
334    {    {
335      send (DATA);      send(DATA);
336      switch (getAllResponses ())      switch (getAllResponses())
337        {        {
338        case SEND_DATA:        case SEND_DATA:
339          return new MessageOutputStream (out);          return new MessageOutputStream(out);
340        default:        default:
341          throw new ProtocolException (response);          throw new ProtocolException(response);
342        }        }
343    }    }
344    
# Line 345  public class SMTPConnection Line 347  public class SMTPConnection
347     * @see #data     * @see #data
348     * @return true id transfer was successful, false otherwise     * @return true id transfer was successful, false otherwise
349     */     */
350    public boolean finishData () throws IOException    public boolean finishData()
351        throws IOException
352    {    {
353      send (FINISH_DATA);      send(FINISH_DATA);
354      switch (getAllResponses ())      switch (getAllResponses())
355        {        {
356        case OK:        case OK:
357          return true;          return true;
# Line 360  public class SMTPConnection Line 363  public class SMTPConnection
363    /**    /**
364     * Aborts the current mail transaction.     * Aborts the current mail transaction.
365     */     */
366    public void rset () throws IOException    public void rset()
367        throws IOException
368    {    {
369      send (RSET);      send(RSET);
370      if (getAllResponses () != OK)      if (getAllResponses() != OK)
371        {        {
372          throw new ProtocolException (response);          throw new ProtocolException(response);
373        }        }
374    }    }
375    
# Line 376  public class SMTPConnection Line 380  public class SMTPConnection
380     * null on failure.     * null on failure.
381     * @param address a mailbox, or real name and mailbox     * @param address a mailbox, or real name and mailbox
382     */     */
383    public List vrfy (String address) throws IOException    public List vrfy(String address)
384        throws IOException
385    {    {
386      String command = VRFY + ' ' + address;      String command = VRFY + ' ' + address;
387      send (command);      send(command);
388      List list = new ArrayList ();      List list = new ArrayList();
389      do      do
390        {        {
391          switch (getResponse ())          switch (getResponse())
392            {            {
393            case OK:            case OK:
394            case AMBIGUOUS:            case AMBIGUOUS:
395              response = response.trim ();              response = response.trim();
396              if (response.indexOf ('@') != -1)              if (response.indexOf('@') != -1)
397                {                {
398                  list.add (response);                  list.add(response);
399                }                }
400              else if (response.indexOf ('<') != -1)              else if (response.indexOf('<') != -1)
401                {                {
402                  list.add (response);                  list.add(response);
403                }                }
404              else if (response.indexOf (' ') == -1)              else if (response.indexOf(' ') == -1)
405                {                {
406                  list.add (response);                  list.add(response);
407                }                }
408              break;              break;
409            default:            default:
# Line 406  public class SMTPConnection Line 411  public class SMTPConnection
411            }            }
412        }        }
413      while (continuation);      while (continuation);
414      return Collections.unmodifiableList (list);      return Collections.unmodifiableList(list);
415    }    }
416    
417    /**    /**
# Line 414  public class SMTPConnection Line 419  public class SMTPConnection
419     * or null on failure.     * or null on failure.
420     * @param address a mailing list name     * @param address a mailing list name
421     */     */
422    public List expn (String address) throws IOException    public List expn(String address)
423        throws IOException
424    {    {
425      String command = EXPN + ' ' + address;      String command = EXPN + ' ' + address;
426      send (command);      send(command);
427      List list = new ArrayList ();      List list = new ArrayList();
428      do      do
429        {        {
430          switch (getResponse ())          switch (getResponse())
431            {            {
432            case OK:            case OK:
433              response = response.trim ();              response = response.trim();
434              list.add (response);              list.add(response);
435              break;              break;
436            default:            default:
437              return null;              return null;
438            }            }
439        }        }
440      while (continuation);      while (continuation);
441      return Collections.unmodifiableList (list);      return Collections.unmodifiableList(list);
442    }    }
443    
444    /**    /**
# Line 442  public class SMTPConnection Line 448  public class SMTPConnection
448     * @return a list of possibly useful information, or null if the command     * @return a list of possibly useful information, or null if the command
449     * failed.     * failed.
450     */     */
451    public List help (String arg) throws IOException    public List help(String arg)
452        throws IOException
453    {    {
454      String command = (arg == null) ? HELP :      String command = (arg == null) ? HELP :
455        HELP + ' ' + arg;        HELP + ' ' + arg;
456      send (command);      send(command);
457      List list = new ArrayList ();      List list = new ArrayList();
458      do      do
459        {        {
460          switch (getResponse ())          switch (getResponse())
461            {            {
462            case INFO:            case INFO:
463              list.add (response);              list.add(response);
464              break;              break;
465            default:            default:
466              return null;              return null;
467            }            }
468        }        }
469      while (continuation);      while (continuation);
470      return Collections.unmodifiableList (list);      return Collections.unmodifiableList(list);
471    }    }
472    
473    /**    /**
474     * Issues a NOOP command.     * Issues a NOOP command.
475     * This does nothing, but can be used to keep the connection alive.     * This does nothing, but can be used to keep the connection alive.
476     */     */
477    public void noop () throws IOException    public void noop()
478        throws IOException
479    {    {
480      send (NOOP);      send(NOOP);
481      getAllResponses ();      getAllResponses();
482    }    }
483    
484    /**    /**
485     * Close the connection to the server.     * Close the connection to the server.
486     */     */
487    public void quit () throws IOException    public void quit()
488        throws IOException
489    {    {
490      try      try
491        {        {
492          send (QUIT);          send(QUIT);
493          getAllResponses ();          getAllResponses();
494          /* RFC 2821 states that the server MUST send an OK reply here, but          /* RFC 2821 states that the server MUST send an OK reply here, but
495           * many don't: postfix, for instance, sends 221.           * many don't: postfix, for instance, sends 221.
496           * In any case we have done our best. */           * In any case we have done our best. */
# Line 492  public class SMTPConnection Line 501  public class SMTPConnection
501      finally      finally
502        {        {
503          // Close the socket anyway.          // Close the socket anyway.
504          socket.close ();          socket.close();
505        }        }
506    }    }
507    
# Line 500  public class SMTPConnection Line 509  public class SMTPConnection
509     * Issues a HELO command.     * Issues a HELO command.
510     * @param hostname the local host name     * @param hostname the local host name
511     */     */
512    public boolean helo (String hostname) throws IOException    public boolean helo(String hostname)
513        throws IOException
514    {    {
515      String command = HELO + ' ' + hostname;      String command = HELO + ' ' + hostname;
516      send (command);      send(command);
517      return (getAllResponses () == OK);      return (getAllResponses() == OK);
518    }    }
519    
520    /**    /**
# Line 514  public class SMTPConnection Line 524  public class SMTPConnection
524     * Otherwise returns null, and HELO should be called.     * Otherwise returns null, and HELO should be called.
525     * @param hostname the local host name     * @param hostname the local host name
526     */     */
527    public List ehlo (String hostname) throws IOException    public List ehlo(String hostname)
528        throws IOException
529    {    {
530      String command = EHLO + ' ' + hostname;      String command = EHLO + ' ' + hostname;
531      send (command);      send(command);
532      List extensions = new ArrayList ();      List extensions = new ArrayList();
533      do      do
534        {        {
535          switch (getResponse ())          switch (getResponse())
536            {            {
537            case OK:            case OK:
538              extensions.add (response);              extensions.add(response);
539              break;              break;
540            default:            default:
541              return null;              return null;
542            }            }
543        }        }
544      while (continuation);      while (continuation);
545      return Collections.unmodifiableList (extensions);      return Collections.unmodifiableList(extensions);
546    }    }
547    
548    /**    /**
# Line 539  public class SMTPConnection Line 550  public class SMTPConnection
550     * This depends on many features, such as the JSSE classes being in the     * This depends on many features, such as the JSSE classes being in the
551     * classpath. Returns true if successful, false otherwise.     * classpath. Returns true if successful, false otherwise.
552     */     */
553    public boolean starttls () throws IOException    public boolean starttls()
554        throws IOException
555    {    {
556      return starttls (new EmptyX509TrustManager ());      return starttls(new EmptyX509TrustManager());
557    }    }
558        
559    /**    /**
# Line 550  public class SMTPConnection Line 562  public class SMTPConnection
562     * classpath. Returns true if successful, false otherwise.     * classpath. Returns true if successful, false otherwise.
563     * @param tm the custom trust manager to use     * @param tm the custom trust manager to use
564     */     */
565    public boolean starttls (TrustManager tm) throws IOException    public boolean starttls(TrustManager tm)
566        throws IOException
567    {    {
568      try      try
569        {        {
570          // Use SSLSocketFactory to negotiate a TLS session and wrap the          // Use SSLSocketFactory to negotiate a TLS session and wrap the
571          // current socket.          // current socket.
572          SSLContext context = SSLContext.getInstance ("TLS");          SSLContext context = SSLContext.getInstance("TLS");
573          // We don't require strong validation of the server certificate          // We don't require strong validation of the server certificate
574          TrustManager[] trust = new TrustManager[] { tm };          TrustManager[] trust = new TrustManager[] { tm };
575          context.init (null, trust, null);          context.init(null, trust, null);
576          SSLSocketFactory factory = context.getSocketFactory ();          SSLSocketFactory factory = context.getSocketFactory();
577                    
578          send (STARTTLS);          send(STARTTLS);
579          if (getAllResponses () != READY)          if (getAllResponses() != READY)
580            {            {
581              return false;              return false;
582            }            }
583                    
584          String hostname = socket.getInetAddress ().getHostName ();          String hostname = socket.getInetAddress().getHostName();
585          int port = socket.getPort ();          int port = socket.getPort();
586          SSLSocket ss =          SSLSocket ss =
587            (SSLSocket) factory.createSocket (socket, hostname, port, true);            (SSLSocket) factory.createSocket(socket, hostname, port, true);
588          String[] protocols = { "TLSv1", "SSLv3" };          String[] protocols = { "TLSv1", "SSLv3" };
589          ss.setEnabledProtocols (protocols);          ss.setEnabledProtocols(protocols);
590          ss.setUseClientMode (true);          ss.setUseClientMode(true);
591          ss.startHandshake ();          ss.startHandshake();
592                    
593          // Set up streams          // Set up streams
594          InputStream in = ss.getInputStream ();          InputStream in = ss.getInputStream();
595          in = new BufferedInputStream (in);          in = new BufferedInputStream(in);
596          in = new CRLFInputStream (in);          in = new CRLFInputStream(in);
597          this.in = new LineInputStream (in);          this.in = new LineInputStream(in);
598          OutputStream out = ss.getOutputStream ();          OutputStream out = ss.getOutputStream();
599          out = new BufferedOutputStream (out);          out = new BufferedOutputStream(out);
600          this.out = new CRLFOutputStream (out);          this.out = new CRLFOutputStream(out);
601          return true;          return true;
602        }        }
603      catch (GeneralSecurityException e)      catch (GeneralSecurityException e)
# Line 604  public class SMTPConnection Line 617  public class SMTPConnection
617     * @param password the authentication credentials     * @param password the authentication credentials
618     * @return true if authentication was successful, false otherwise     * @return true if authentication was successful, false otherwise
619     */     */
620    public boolean authenticate (String mechanism, String username,    public boolean authenticate(String mechanism, String username,
621                                 String password) throws IOException                                String password) throws IOException
622    {    {
623      try      try
624        {        {
625          String[] m = new String[] { mechanism };          String[] m = new String[] { mechanism };
626          CallbackHandler ch = new SaslCallbackHandler (username, password);          CallbackHandler ch = new SaslCallbackHandler(username, password);
627          // Avoid lengthy callback procedure for GNU Crypto          // Avoid lengthy callback procedure for GNU Crypto
628          Properties p = new Properties ();          Properties p = new Properties();
629          p.put ("gnu.crypto.sasl.username", username);          p.put("gnu.crypto.sasl.username", username);
630          p.put ("gnu.crypto.sasl.password", password);          p.put("gnu.crypto.sasl.password", password);
631          SaslClient sasl =          SaslClient sasl =
632            Sasl.createSaslClient (m, null, "smtp",            Sasl.createSaslClient(m, null, "smtp",
633                                   socket.getInetAddress ().getHostName (),                                  socket.getInetAddress().getHostName(),
634                                   p, ch);                                  p, ch);
635          if (sasl == null)          if (sasl == null)
636            {            {
637              // Fall back to home-grown SASL clients              // Fall back to home-grown SASL clients
638              if ("LOGIN".equalsIgnoreCase (mechanism))              if ("LOGIN".equalsIgnoreCase(mechanism))
639                {                {
640                  sasl = new SaslLogin (username, password);                  sasl = new SaslLogin(username, password);
641                }                }
642              else if ("PLAIN".equalsIgnoreCase (mechanism))              else if ("PLAIN".equalsIgnoreCase(mechanism))
643                {                {
644                  sasl = new SaslPlain (username, password);                  sasl = new SaslPlain(username, password);
645                }                }
646              else if ("CRAM-MD5".equalsIgnoreCase (mechanism))              else if ("CRAM-MD5".equalsIgnoreCase(mechanism))
647                {                {
648                  sasl = new SaslCramMD5 (username, password);                  sasl = new SaslCramMD5(username, password);
649                }                }
650              else              else
651                {                {
# Line 640  public class SMTPConnection Line 653  public class SMTPConnection
653                }                }
654            }            }
655                    
656          StringBuffer cmd = new StringBuffer (AUTH);          StringBuffer cmd = new StringBuffer(AUTH);
657          cmd.append (' ');          cmd.append(' ');
658          cmd.append (mechanism);          cmd.append(mechanism);
659          if (sasl.hasInitialResponse ())          if (sasl.hasInitialResponse())
660            {            {
661              cmd.append (' ');              cmd.append(' ');
662              byte[] init = sasl.evaluateChallenge (new byte[0]);              byte[] init = sasl.evaluateChallenge(new byte[0]);
663              if (init.length == 0)              if (init.length == 0)
664                {                {
665                  cmd.append ('=');                  cmd.append('=');
666                }                }
667              else              else
668                {                {
669                  cmd.append (new String (BASE64.encode (init), "US-ASCII"));                  cmd.append(new String(BASE64.encode(init), "US-ASCII"));
670                }                }
671            }            }
672          send (cmd.toString ());          send(cmd.toString());
673          while (true)          while (true)
674            {            {
675              switch (getAllResponses ())              switch (getAllResponses())
676                {                {
677                case 334:                case 334:
678                  try                  try
679                    {                    {
680                      byte[] c0 = response.getBytes ("US-ASCII");                      byte[] c0 = response.getBytes("US-ASCII");
681                      byte[] c1 = BASE64.decode (c0);       // challenge                      byte[] c1 = BASE64.decode(c0);       // challenge
682                      byte[] r0 = sasl.evaluateChallenge (c1);                      byte[] r0 = sasl.evaluateChallenge(c1);
683                      byte[] r1 = BASE64.encode (r0);       // response                      byte[] r1 = BASE64.encode(r0);       // response
684                      out.write (r1);                      out.write(r1);
685                      out.write (0x0d);                      out.write(0x0d);
686                      out.flush ();                      out.flush();
687                      if (debug)                      if (debug)
688                        {                        {
689                          Logger logger = Logger.getInstance ();                          Logger logger = Logger.getInstance();
690                          logger.log ("smtp", "> " +                          logger.log("smtp", "> " +
691                                      new String (r1, "US-ASCII"));                                      new String(r1, "US-ASCII"));
692                        }                        }
693                    }                    }
694                  catch (SaslException e)                  catch (SaslException e)
695                    {                    {
696                      // Error in SASL challenge evaluation - cancel exchange                      // Error in SASL challenge evaluation - cancel exchange
697                      out.write (0x2a);                      out.write(0x2a);
698                      out.write (0x0d);                      out.write(0x0d);
699                      out.flush ();                      out.flush();
700                      if (debug)                      if (debug)
701                        {                        {
702                          Logger logger = Logger.getInstance ();                          Logger logger = Logger.getInstance();
703                          logger.log ("smtp", "> *");                          logger.log("smtp", "> *");
704                        }                        }
705                    }                    }
706                  break;                  break;
707                case 235:                case 235:
708                  String qop = (String) sasl.getNegotiatedProperty (Sasl.QOP);                  String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP);
709                  if ("auth-int".equalsIgnoreCase (qop)                  if ("auth-int".equalsIgnoreCase(qop)
710                      || "auth-conf".equalsIgnoreCase (qop))                      || "auth-conf".equalsIgnoreCase(qop))
711                    {                    {
712                      InputStream in = socket.getInputStream ();                      InputStream in = socket.getInputStream();
713                      in = new BufferedInputStream (in);                      in = new BufferedInputStream(in);
714                      in = new SaslInputStream (sasl, in);                      in = new SaslInputStream(sasl, in);
715                      in = new CRLFInputStream (in);                      in = new CRLFInputStream(in);
716                      this.in = new LineInputStream (in);                      this.in = new LineInputStream(in);
717                      OutputStream out = socket.getOutputStream ();                      OutputStream out = socket.getOutputStream();
718                      out = new BufferedOutputStream (out);                      out = new BufferedOutputStream(out);
719                      out = new SaslOutputStream (sasl, out);                      out = new SaslOutputStream(sasl, out);
720                      this.out = new CRLFOutputStream (out);                      this.out = new CRLFOutputStream(out);
721                    }                    }
722                  return true;                  return true;
723                default:                default:
# Line 730  public class SMTPConnection Line 743  public class SMTPConnection
743     * Send the specified command string to the server.     * Send the specified command string to the server.
744     * @param command the command to send     * @param command the command to send
745     */     */
746    protected void send (String command) throws IOException    protected void send(String command)
747        throws IOException
748    {    {
749      if (debug)      if (debug)
750        {        {
751          Logger logger = Logger.getInstance ();          Logger logger = Logger.getInstance();
752          logger.log ("smtp", "> " + command);          logger.log("smtp", "> " + command);
753        }        }
754      out.write (command.getBytes ("US-ASCII"));      out.write(command.getBytes("US-ASCII"));
755      out.write (0x0d);      out.write(0x0d);
756      out.flush ();      out.flush();
757    }    }
758        
759    /**    /**
760     * Returns the next response from the server.     * Returns the next response from the server.
761     */     */
762    protected int getResponse () throws IOException    protected int getResponse()
763        throws IOException
764    {    {
765      String line = null;      String line = null;
766      try      try
767        {        {
768          line = in.readLine ();          line = in.readLine();
769          // Handle special case eg 334 where CRLF occurs after code.          // Handle special case eg 334 where CRLF occurs after code.
770          if (line.length () < 4)          if (line.length() < 4)
771            {            {
772              line = line + '\n' + in.readLine();              line = line + '\n' + in.readLine();
773            }            }
774          if (debug)          if (debug)
775            {            {
776              Logger logger = Logger.getInstance ();              Logger logger = Logger.getInstance();
777              logger.log ("smtp", "< " + line);              logger.log("smtp", "< " + line);
778            }            }
779          int code = Integer.parseInt (line.substring (0, 3));          int code = Integer.parseInt(line.substring(0, 3));
780          continuation = (line.charAt (3) == '-');          continuation = (line.charAt(3) == '-');
781          response = line.substring (4);          response = line.substring(4);
782          return code;          return code;
783        }        }
784      catch (NumberFormatException e)      catch (NumberFormatException e)
785        {        {
786          throw new ProtocolException ("Unexpected response: " + line);          throw new ProtocolException("Unexpected response: " + line);
787        }        }
788    }    }
789    
# Line 778  public class SMTPConnection Line 793  public class SMTPConnection
793     * continuation ceases. If a different response code from the first is     * continuation ceases. If a different response code from the first is
794     * encountered, this causes a protocol exception.     * encountered, this causes a protocol exception.
795     */     */
796    protected int getAllResponses () throws IOException    protected int getAllResponses()
797        throws IOException
798    {    {
799      int code1, code;      int code1, code;
800      boolean err = false;      boolean err = false;
801      code1 = code = getResponse ();      code1 = code = getResponse();
802      while (continuation)      while (continuation)
803        {        {
804          code = getResponse();          code = getResponse();
# Line 793  public class SMTPConnection Line 809  public class SMTPConnection
809        }        }
810      if (err)      if (err)
811        {        {
812          throw new ProtocolException ("Conflicting response codes");          throw new ProtocolException("Conflicting response codes");
813        }        }
814      return code;      return code;
815    }    }
816    
817  }  }
818    

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26