system.net.mail.smtpclient fqdn required

This seems to be the right place to ask this question.

I'm trying to send a simple email message using the SmtpClient in system.net.mail through my own Postfix mail server. I've got UCE controls turned on and the .Send method is rightfully failing during the HELO negotiation because the FQDN of the sending host is not being sent. I don't see anywhere to force this behavior, or to otherwise set the FQDN on the SmtpClient object.

I'm missing something somewhere.

Sean



Answer this question

system.net.mail.smtpclient fqdn required

  • GetOuraThatGarden

    I am working on that :-)

  • Sabaawy

    Thanks for making this suggestion, Richard.

    I'd like to suggest a change in wording. The problem statement says:

    The current implementation of the System.Net.Mail.SmtpClient
    uses the NetBIOS name of the computer in the HELO / EHLO
    commands. Many anti-spam systems require the FQDN instead.
    As a result, email sent with the SmtpClient class is often blocked.

    In fact, this behavior is required by the SMTP RFC, 821. I think that defining the problem in terms of specification compliance is a stronger argument for the change.

    Sean


  • Niels Flensted

    RFC821 (August 1982) isn't entirely clear about what is required - it simply specifies "the host name". However, it has since been replaced with RFC2821 (April 2001), which clearly requires the FQDN:

    "A domain name that is not in FQDN form ... MUST NOT appear in any SMTP transaction."

    I've updated the suggestion to include this information.

  • Andrewyyy

    Ach, 2821, right, that's what I meant! :)

    Thanks for ammending the request. It's certainly much more precise.

    I'll look forward to a correctly functioning smtpclient someday! ;)

    Sean


  • MorB

    Until Microsoft fix the SmtpClient, the only solution is to use reflection to change the private "localHostName" field to the FQDN:


    using System;
    using System.Net.Mail;
    using System.Net.NetworkInformation;
    using System.Reflection;

    namespace Trinet.Net.Mail
    {
    /// <summary>
    /// An extended <see cref="SmtpClient"/> which sends the
    /// FQDN of the local machine in the EHLO/HELO command.
    /// </summary>
    public class SmtpClientEx : SmtpClient
    {
    #region Private Data

    private static readonly FieldInfo localHostName = GetLocalHostNameField();

    #endregion

    #region Constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="SmtpClientEx"/> class
    /// that sends e-mail by using the specified SMTP server and port.
    /// </summary>
    /// <param name="host">
    /// A <see cref="String"/> that contains the name or
    /// IP address of the host used for SMTP transactions.
    /// </param>
    /// <param name="port">
    /// An <see cref="Int32"/> greater than zero that
    /// contains the port to be used on host.
    /// </param>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="port"/> cannot be less than zero.
    /// </exception>
    public SmtpClientEx(string host, int port) : base(host, port)
    {
    Initialize();
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="SmtpClientEx"/> class
    /// that sends e-mail by using the specified SMTP server.
    /// </summary>
    /// <param name="host">
    /// A <see cref="String"/> that contains the name or
    /// IP address of the host used for SMTP transactions.
    /// </param>
    public SmtpClientEx(string host) : base(host)
    {
    Initialize();
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="SmtpClientEx"/> class
    /// by using configuration file settings.
    /// </summary>
    public SmtpClientEx()
    {
    Initialize();
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the local host name used in SMTP transactions.
    /// </summary>
    /// <value>
    /// The local host name used in SMTP transactions.
    /// This should be the FQDN of the local machine.
    /// </value>
    /// <exception cref="ArgumentNullException">
    /// The property is set to a value which is
    /// <see langword="null"/> or <see cref="String.Empty"/>.
    /// </exception>
    public string LocalHostName
    {
    get
    {
    if (null == localHostName) return null;
    return (string)localHostName.GetValue(this);
    }
    set
    {
    if (string.IsNullOrEmpty(value))
    {
    throw new ArgumentNullException("value");
    }
    if (null != localHostName)
    {
    localHostName.SetValue(this, value);
    }
    }
    }

    #endregion

    #region Methods

    /// <summary>
    /// Returns the price "localHostName" field.
    /// </summary>
    /// <returns>
    /// The <see cref="FieldInfo"/> for the private
    /// "localHostName" field.
    /// </returns>
    private static FieldInfo GetLocalHostNameField()
    {
    BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
    return typeof(SmtpClient).GetField("localHostName", flags);
    }

    /// <summary>
    /// Initializes the local host name to
    /// the FQDN of the local machine.
    /// </summary>
    private void Initialize()
    {
    IPGlobalProperties ip = IPGlobalProperties.GetIPGlobalProperties();
    if (!string.IsNullOrEmpty(ip.HostName) && !string.IsNullOrEmpty(ip.DomainName))
    {
    this.LocalHostName = ip.HostName + "." + ip.DomainName;
    }
    }

    #endregion
    }
    }


  • smitra

    Any luck finding a resolution to this I'm having the same problem. My company's mail servers require the FQDN, but when I launch my email web app through visual studio and watch the traffic I see it's only providing the NetBIOS name after the "EHLO" and not the FQDN. Please help!
  • Sundance Kid

    Hi Durgaprasad.

    I've been referring to RFC 821, 2821, and 1123. Indeed the FQDN or IP can be provided by HELO (or EHLO), but I can't find any reference about assuming the domain of the server if FQDN isn't supplied. I'd love to know if indeed that's true.

    I added the requested section to the app.config file and but the resultant trace doesn't look much different to my eye. Here's the Sources section just to make sure it's right and the trace is further down.

    <source name="System.Net.Sockets">
    <listeners>
    <add name="TraceLog"/>
    </listeners>
    </source>
    <!-- This section defines the logging configuration for My.Application.Log -->
    <source name="DefaultSource" switchName="DefaultSwitch">
    <listeners>
    <add name="FileLog"/>
    <!-- Uncomment the below section to write to the Application Event Log -->
    <!--<add name="EventLog"/>-->
    </listeners>
    </source>
    </sources>

    TRACE:

    System.Net Information: 0 : [2560] Associating MailMessage#50934842 with Message#10366524
    System.Net Verbose: 0 : [2560] SmtpClient::.ctor(host=192.168.0.1)
    System.Net Information: 0 : [2560] Associating SmtpClient#63840421 with SmtpTransport#54246671
    System.Net Verbose: 0 : [2560] Exiting SmtpClient::.ctor() -> SmtpClient#63840421
    System.Net Verbose: 0 : [2560] SmtpClient#63840421::Send(MailMessage#50934842)
    System.Net Information: 0 : [2560] SmtpClient#63840421::Send(DeliveryMethod=Network)
    System.Net Information: 0 : [2560] Associating SmtpClient#63840421 with MailMessage#50934842
    System.Net Information: 0 : [2560] Associating SmtpTransport#54246671 with SmtpConnection#25181126
    System.Net Information: 0 : [2560] Associating SmtpConnection#25181126 with ServicePoint#59408853
    System.Net Information: 0 : [2560] Associating SmtpConnection#25181126 with SmtpPooledStream#56152722
    System.Net Error: 0 : [2560] Exception in the SmtpClient#63840421::Send - Command parameter not implemented. The server response was: <bo>: Helo command rejected: need fully-qualified hostname
    System.Net Error: 0 : [2560] at System.Net.Mail.RecipientCommand.CheckResponse(SmtpStatusCode statusCode, String response)
    at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
    at System.Net.Mail.SmtpClient.Send(MailMessage message)
    System.Net Error: 0 : [2560] Exception in the
    #12036987::UnhandledExceptionHandler - Command parameter not implemented. The server response was: <bo>: Helo command rejected: need fully-qualified hostname
    System.Net Error: 0 : [2560] at System.Net.Mail.RecipientCommand.CheckResponse(SmtpStatusCode statusCode, String response)
    at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
    at System.Net.Mail.SmtpClient.Send(MailMessage message)
    at MRRS_GUI.frmLogin.Button1_Click(Object sender, EventArgs e) in I:\srjc\sp2k6\vb6821\MRRS\MRRS_GUI\frmLogin.vb:line 78
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.Run(ApplicationContext context)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    at MRRS_GUI.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
    at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()
    System.Net Verbose: 0 : [2560] Exiting SmtpClient#63840421::Send()


  • Buhmann

    Sean,
    Could you add the sockets level tacing to your config file
    <source name="System.Net.Sockets">
    <listeners>
    <add name="MyTraceFile"/>
    </listeners>
    </source>

    That way we could see what is going on the wire at the sockets level.

    I read the RFC and it seems that we should send the FQDN or an IPAddress. I also read in some other RFC that if we don't send the FQDN the server must assume the domain name of the server itself. Let me do some more research.
    Please let me know which RFC you are referring to.



  • Ahmad Ariff Baharudin

    I'm in the same boat... trying to send mail directly to mx record for server instead of relaying through my mailserver.  Works good except for FQDN and no backwards compat with HELO.

    If anyone has suggestions or status info, I'm all ears :)


  • anton_tu

    Weve encountered the same problem.

    Tried:

    * disabling the netbios via wins

    * Placing entries into hosts file

    Interestingly using another marketed .NET Email control namespace, it also does the same thing.... a point to note is that this Namespace is built on .net framework 1.1 not 2.0.

    We are currently trying all sorts of DNS tricks to try and resolve this but given what I've learned from the posts above, Im begining to wonder if a solution even exists.

    Under IIS smtp there is an option for supplying "Fully Qualified domain name". Why is such a setting unavailable for system.net.mail

    Is this tool simply unintended for direct SMTP mailout Is the intended design usage (ideally) to specify a relay server

    Example SMTP session of what goes wrong:

    220 postoffice03.mail-hub.dodo.com.au service ready

    EHLO DEV-TEMP

    550-HELO/EHLO must contain a FQDN or IP literal

    HELO DEV-TEMP

    550 please see RFC 2821 section 4.1.1.1 Forcing disconnection from SMTP server.

    QUIT

    550-HELO/EHLO must contain a FQDN or IP literal Disconnected.

    I'd really like to see some resolution to this. Its already having implications on our production environment applications.


  • Tintxo

    Hi,

    I have the same Problem....

    Obviously there is no Solution in .NET 2.

    Do you know if the SMTPClient is changed in .NET 3

    Chris


  • Bradley Lane

    It looks like there is no way to make the SmtpClient send the FQDN in the HELO / EHLO command. The parameter is taken from the internal localHostName field of the SmtpClient class, which is initialized to the NetBIOS host name in the private Initialize method.

    I've logged a suggestion that this behavior should be changed:
    http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx feedbackid=d31e8d9e-9839-4c86-876b-ca5af1910091

  • DaManJ

    Why would you need the FQDN of the sending host
    Could you send me the system.net trace file for this

    Look at http://blogs.msdn.com/dgorti for instructions on how to get a trace



  • GuySmiley

    The FQDN from the sending host is used in the UCE controls of Postfix to ensure that the sending host can be found using a reverse DNS lookup. This is a strict enforcement of RFC 821 used by many SMTP servers to help reduce SPAM. The rationale is that if a domain specified in a HELO message cannot be found using rDNS, it probably doesn't exist and therefore is more likely to be used for some nefarious reason.

    It would seem reasonable to have an option to enable the FQDN to be sent by the .Net SmtpClient.

    By the way, your blog had an interesting comment about NetMon. However, when I tried to install it using the instructions you gave (on WinXP SP2) there was no NetMon option available to install.

    Thanks for your help.

    Here's the trace.

     

    System.Net Information: 0 : [2424] Associating MailMessage#37535352 with Message#46630754
    System.Net Verbose: 0 : [2424] SmtpClient::.ctor(host=192.168.0.1)
    System.Net Information: 0 : [2424] Associating SmtpClient#47616313 with SmtpTransport#16973140
    System.Net Verbose: 0 : [2424] Exiting SmtpClient::.ctor()  -> SmtpClient#47616313
    System.Net Verbose: 0 : [2424] SmtpClient#47616313::Send(MailMessage#37535352)
    System.Net Information: 0 : [2424] SmtpClient#47616313::Send(DeliveryMethod=Network)
    System.Net Information: 0 : [2424] Associating SmtpClient#47616313 with MailMessage#37535352
    System.Net Information: 0 : [2424] Associating SmtpTransport#16973140 with SmtpConnection#24026409
    System.Net Information: 0 : [2424] Associating SmtpConnection#24026409 with ServicePoint#16561909
    System.Net Information: 0 : [2424] Associating SmtpConnection#24026409 with SmtpPooledStream#57566403
    System.Net Error: 0 : [2424] Exception in the SmtpClient#47616313::Send - Command parameter not implemented. The server response was: <bo>: Helo command rejected: need fully-qualified hostname
    System.Net Error: 0 : [2424]    at System.Net.Mail.RecipientCommand.CheckResponse(SmtpStatusCode statusCode, String response)
       at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
    System.Net Error: 0 : [2424] Exception in the
    #35320229::UnhandledExceptionHandler - Command parameter not implemented. The server response was: <bo>: Helo command rejected: need fully-qualified hostname
    System.Net Error: 0 : [2424]    at System.Net.Mail.RecipientCommand.CheckResponse(SmtpStatusCode statusCode, String response)
       at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
       at MRRS_GUI.frmLogin.Button1_Click(Object sender, EventArgs e) in I:\srjc\sp2k6\vb6821\MRRS\MRRS_GUI\frmLogin.vb:line 79
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at MRRS_GUI.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
    System.Net Verbose: 0 : [2424] Exiting SmtpClient#47616313::Send()


  • system.net.mail.smtpclient fqdn required