public void CanMakeNoop() { // arrange var enumerator = new TokenEnumerator(new StringTokenReader("NOOP")); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeNoop(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is NoopCommand); }
public void CanMakeQuit() { // arrange var enumerator = new TokenEnumerator(new Token(TokenKind.Text, "QUIT")); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeQuit(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is QuitCommand); }
public void CanNotMakeHelo(string input) { // arrange var enumerator = new TokenEnumerator(new StringTokenReader(input)); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeHelo(enumerator, out command, out errorResponse); // assert Assert.False(result); Assert.Null(command); Assert.NotNull(errorResponse); }
public void CanMakeHelo() { // arrange var enumerator = new TokenEnumerator(new StringTokenReader("HELO abc-1-def.mail.com")); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeHelo(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is HeloCommand); Assert.Equal("abc-1-def.mail.com", ((HeloCommand)command).Domain); }
/// <summary> /// Make an NOOP command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The NOOP command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeNoop(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "NOOP")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); if (enumerator.Count > 1) { _logger.LogVerbose("NOOP command can not have parameters (found {0} parameters).", enumerator.Count); errorResponse = SmtpResponse.SyntaxError; return false; } command = NoopCommand.Instance; return true; }
/// <summary> /// Make a RCTP command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The RCTP command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeRcpt(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "RCPT")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); if (enumerator.Take() != new Token(TokenKind.Text, "TO") || enumerator.Take() != new Token(TokenKind.Punctuation, ":")) { errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, "missing the TO:"); return false; } // according to the spec, whitespace isnt allowed here anyway enumerator.TakeWhile(TokenKind.Space); IMailbox mailbox; if (_parser.TryMakePath(enumerator, out mailbox) == false) { _logger.LogVerbose("Syntax Error (Text={0})", enumerator.AsText()); errorResponse = SmtpResponse.SyntaxError; return false; } // TODO: support optional service extension parameters here command = new RcptCommand(mailbox, _options.MailboxFilterFactory); return true; }
/// <summary> /// Make a MAIL command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The MAIL command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeMail(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "MAIL")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); if (enumerator.Take() != new Token(TokenKind.Text, "FROM") || enumerator.Take() != new Token(TokenKind.Punctuation, ":")) { errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, "missing the FROM:"); return false; } // according to the spec, whitespace isnt allowed here but most servers send it enumerator.TakeWhile(TokenKind.Space); IMailbox mailbox; if (_parser.TryMakeReversePath(enumerator, out mailbox) == false) { _logger.LogVerbose("Syntax Error (Text={0})", enumerator.AsText()); errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError); return false; } // match the optional (ESMTP) parameters IDictionary<string, string> parameters; if (_parser.TryMakeMailParameters(enumerator, out parameters) == false) { parameters = new Dictionary<string, string>(); } command = new MailCommand(mailbox, parameters, _options.MailboxFilterFactory); return true; }
/// <summary> /// Make an EHLO command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The EHLO command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeEhlo(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "EHLO")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); string domain; if (_parser.TryMakeDomain(enumerator, out domain)) { command = new EhloCommand(domain, _options); return true; } string address; if (_parser.TryMakeAddressLiteral(enumerator, out address)) { command = new EhloCommand(address, _options); return true; } errorResponse = SmtpResponse.SyntaxError; return false; }
/// <summary> /// Make a HELO command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The HELO command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeHelo(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "HELO")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); string domain; if (_parser.TryMakeDomain(enumerator, out domain) == false) { _logger.LogVerbose("Could not match the domain name (Text={0}).", enumerator.AsText()); errorResponse = SmtpResponse.SyntaxError; return false; } command = new HeloCommand(domain); return true; }
/// <summary> /// Constructor. /// </summary> /// <param name="tokenEnumerator">The token enumerator to create the checkpoint on.</param> internal TokenEnumeratorCheckpoint(TokenEnumerator tokenEnumerator) { _tokenEnumerator = tokenEnumerator; _index = tokenEnumerator._index; }
public void CanMakeMailWithBlankAddress() { // arrange var enumerator = new TokenEnumerator(new StringTokenReader("MAIL FROM:< >")); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeMail(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is MailCommand); Assert.Null(((MailCommand)command).Address); }
/// <summary> /// Make an AUTH command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The AUTH command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeAuth(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "AUTH")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); AuthenticationMethod method; if (Enum.TryParse(enumerator.Peek().Text, true, out method) == false) { _logger.LogVerbose("AUTH command requires a valid method (PLAIN or LOGIN)"); errorResponse = SmtpResponse.SyntaxError; return false; } enumerator.Take(); string parameter = null; if (enumerator.Count > 0 && _parser.TryMakeBase64(enumerator, out parameter) == false) { _logger.LogVerbose("AUTH parameter must be a Base64 encoded string"); errorResponse = SmtpResponse.SyntaxError; return false; } command = new AuthCommand(_options.UserAuthenticator, method, parameter); return true; }
public void CanMakeEhlo(string input) { // arrange var enumerator = new TokenEnumerator(new StringTokenReader(input)); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeEhlo(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is EhloCommand); Assert.Equal(input.Substring(5), ((EhloCommand)command).DomainOrAddress); }
public void CanMakeRcpt() { // arrange var enumerator = new TokenEnumerator(new StringTokenReader("RCPT TO:<*****@*****.**>")); // act SmtpCommand command; SmtpResponse errorResponse; var result = _smtpCommandFactory.TryMakeRcpt(enumerator, out command, out errorResponse); // assert Assert.True(result); Assert.True(command is RcptCommand); Assert.Equal("cain.osullivan", ((RcptCommand)command).Address.User); Assert.Equal("gmail.com", ((RcptCommand)command).Address.Host); }
/// <summary> /// Make a DATA command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The DATA command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeData(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "DATA")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); if (enumerator.Count > 1) { _logger.LogVerbose("DATA command can not have parameters (Tokens={0})", enumerator.Count); errorResponse = SmtpResponse.SyntaxError; return false; } command = new DataCommand(_options.MessageStoreFactory); return true; }
/// <summary> /// Make an STARTTLS command from the given enumerator. /// </summary> /// <param name="enumerator">The enumerator to create the command from.</param> /// <param name="command">The STARTTLS command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>Returns true if a command could be made, false if not.</returns> public bool TryMakeStartTls(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse) { Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "STARTTLS")); command = null; errorResponse = null; enumerator.Take(); enumerator.TakeWhile(TokenKind.Space); if (enumerator.Count > 1) { _logger.LogVerbose("STARTTLS command can not have parameters (Tokens={0})", enumerator.Count); errorResponse = SmtpResponse.SyntaxError; return false; } command = new StartTlsCommand(_options.ServerCertificate); return true; }
/// <summary> /// Advances the enumerator to the next command in the stream. /// </summary> /// <param name="tokenEnumerator">The token enumerator to accept the command from.</param> /// <param name="command">The command that was found.</param> /// <param name="errorResponse">The error response that indicates why a command could not be accepted.</param> /// <returns>true if a valid command was found, false if not.</returns> public bool TryAccept(TokenEnumerator tokenEnumerator, out SmtpCommand command, out SmtpResponse errorResponse) { return _stateTable.TryAccept(tokenEnumerator, out command, out errorResponse); }
/// <summary> /// Advances the enumerator to the next command in the stream. /// </summary> /// <param name="tokenEnumerator">The token enumerator to accept the command from.</param> /// <param name="command">The command that is defined within the token enumerator.</param> /// <param name="errorResponse">The error that indicates why the command could not be made.</param> /// <returns>true if a valid command was found, false if not.</returns> public bool TryAccept(TokenEnumerator tokenEnumerator, out SmtpCommand command, out SmtpResponse errorResponse) { // lookup the correct action Tuple<State.TryMakeDelegate, SmtpState> action; if (_state.Actions.TryGetValue(tokenEnumerator.Peek().Text, out action) == false) { var response = $"expected {String.Join("/", _state.Actions.Keys)}"; command = null; errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, response); return false; } if (action.Item1(tokenEnumerator, out command, out errorResponse) == false) { return false; } // transition to the next state _state = _states[action.Item2]; return true; }