The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Suspended email accounts accept / bounce mail

Discussion in 'E-mail Discussions' started by mtindor, Mar 31, 2016.

  1. mtindor

    mtindor Well-Known Member

    Joined:
    Sep 14, 2004
    Messages:
    1,279
    Likes Received:
    36
    Trophy Points:
    48
    Location:
    inside a catfish
    cPanel Access Level:
    Root Administrator
    Hello,

    I just realized today that for email accounts which are suspended, cPanel accepts the email to that email account and then bounces back a notice that the account is suspended. That is bad behavior. Email that cannot be delivered due to account suspension should be rejected during SMTP rather than accepted/bounced.

    If I send an email to nonexistent user noway2@somedomain.com, the server appropriately rejects the email during SMTP.
    Code:
    2016-03-31 10:02:08 [704534] H=mail-vk0-f43.google.com [209.85.213.43]:36454 I=[1.2.3.4]:25 X=TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128 CV=no SNI="somedomain.com" F=<BOGUSADDRESS@gmail.com> rejected RCPT <noway2@somedomain.com>: No such person at this address
    
    If I send an email to an existing email account that is suspended, such as noway@somedomain.com, the mail is accepted and then bounced.

    Code:
    2016-03-31 10:00:45 [703882] 1ald9R-002x6w-SO H=mail-vk0-f43.google.com [209.85.213.43]:34831 I=[1.2.3.4]:25 Warning: Message has been scanned: no virus or other harmful content was found
    2016-03-31 10:01:00 [703882] 1ald9R-002x6w-SO H=mail-vk0-f43.google.com [209.85.213.43]:34831 I=[1.2.3.4]:25 Warning: "SpamAssassin as beefy detected message as NOT spam (-1.2)"
    2016-03-31 10:01:00 [703882] 1ald9R-002x6w-SO <= BOGUSADDRESS@gmail.com H=mail-vk0-f43.google.com [209.85.213.43]:34831 I=[1.2.3.4]:25 P=esmtps X=TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128 CV=no SNI="somedomain.com" S=4151 M8S=0 id=CAG1mBRjErV+CG5GVTg6wJiv=B=SzWVOrrYb1zvpadU1ricgLew@mail.gmail.com T="no way jose" from <BOGUSADDRESS@gmail.com> for noway@somedomain.com
    2016-03-31 10:01:00 [703942] cwd=/var/spool/exim 3 args: /usr/sbin/exim -Mc 1ald9R-002x6w-SO
    2016-03-31 10:01:00 [703942] 1ald9R-002x6w-SO ** noway@somedomain.com F=<BOGUSADDRESS@gmail.com> R=virtual_user_filter: This email account's owner has suspended delivery for the account.
    2016-03-31 10:01:00 [703947] cwd=/var/spool/exim 7 args: /usr/sbin/exim -t -oem -oi -f <> -E1ald9R-002x6w-SO
    2016-03-31 10:01:00 [703947] 1ald9g-002x7z-5O <= <> R=1ald9R-002x6w-SO U=mailnull P=local S=5408 M8S=0 T="Mail delivery failed: returning message to sender" from <> for BOGUSADDRESS@gmail.com
    2016-03-31 10:01:00 [703942] 1ald9R-002x6w-SO Completed QT=15s
    
    This is confirmed by the fact that if I send an email to noway@somedomain.com (a bonafide email account that is suspended), I will get an email back from Mailer-Daemon@my.cpanel.server, and if I send an email (from my Gmail account) to noway2@somedomain.com (a nonexistent email account), I will get an email back from mailer-daemon@googlemail.com.

    Mike
     
    #1 mtindor, Mar 31, 2016
    Last edited by a moderator: Apr 1, 2016
    sneader likes this.
  2. sneader

    sneader Well-Known Member

    Joined:
    Aug 21, 2003
    Messages:
    1,126
    Likes Received:
    21
    Trophy Points:
    38
    Location:
    La Crosse, WI
    cPanel Access Level:
    Root Administrator
    I would definitely prefer that emails were rejected at SMTP time. This is just another "queue filler"

    - Scott
     
  3. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    30,678
    Likes Received:
    653
    Trophy Points:
    113
    cPanel Access Level:
    Root Administrator
    Hello :)

    Here's what the filter rule looks like in "/home/$username/etc/$domain/$email-user/filter"after suspending incoming email for a specific email account:

    Code:
    # Exim filter - auto-generated by cPanel.
    #
    # Do not manually edit this file; instead, use cPanel APIs to manipulate
    # email filters. MANUAL CHANGES TO THIS FILE WILL BE OVERWRITTEN.
    #
    # SUSPEND RECEPTION OF NEW MESSAGES
    fail "This email account's owner has suspended delivery for the account."
    
    if not first_delivery and error_message then finish endif
    The design decision to not reject these messages at SMTP time was based on resource efficiency. The filter files are already checked during message delivery, so it does not require additional disk I/O to implement the feature this way. Feel free to open a feature request if you would like an option to block messages at SMTP time:

    Submit A Feature Request

    To note, cPanel version 56 introduces the ability to disable outgoing email:

    As a host, I want to be able to disable outbound email for an account when it has been compromised

    Thank you.
     
  4. sparek-3

    sparek-3 Well-Known Member

    Joined:
    Aug 10, 2002
    Messages:
    1,381
    Likes Received:
    23
    Trophy Points:
    38
    cPanel Access Level:
    Root Administrator
    I've been saying this for years, nobody seems to want to listen.

    You can't fail messages after the SMTP server has already accepted the message.

    This means you can't create filters - Account Level or User Level - that fail messages. It will just create a ton of bounceback messages.

    If you want to fail message, you do that at SMTP time. When you do an SMTP transaction and that last period on a line by itself ("354 Enter message, ending with "." on a line by itself"). If the SMTP server sends a 250 response, then the message has been accepted. The SMTP server does not need to fail the message after that point or you're going to get bounceback backscatter.

    If you really want to fail messages based on filters, then you need to read all of the filters during the SMTP transaction and generate a a 500 level response at that last period on a line by itself. I agree that would be highly CPU intensive, so I would just avoid it completely. I would suggest that you accept the messages and then silently blackhole (save /dev/null) the messages that hit filters after the SMTP transaction has been accepted.
     
  5. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    30,678
    Likes Received:
    653
    Trophy Points:
    113
    cPanel Access Level:
    Root Administrator
  6. sparek-3

    sparek-3 Well-Known Member

    Joined:
    Aug 10, 2002
    Messages:
    1,381
    Likes Received:
    23
    Trophy Points:
    38
    cPanel Access Level:
    Root Administrator
    Fail never should be used in any filter file (/etc/vfilters/example.tld or /home/user/etc/example.tld/email/filter). Why this concept is so hard to grasp is something I don't understand. Fortunately, because this uses a field that is mostly static (the recipient's email address) this can be made to work properly with a small adjustment to the Exim configuration and a couple of hooks.

    Start by creating the necessary files and directories, needed for this.

    Code:
    touch /etc/suspended_incoming
    chown root:mail /etc/suspended_incoming
    chmod 640 /etc/suspended_incoming
    mkdir /var/cpanel/hooks
    Now, save the attached fixincomingsuspend.php.txt file as - /var/cpanel/hooks/fixincomingsuspend.php

    Change the perissions on this file accordingly:

    Code:
    chmod 700 /var/cpanel/hooks/fixincomingsuspend.php
    Add this to the hook registry:

    Code:
    /usr/local/cpanel/bin/manage_hooks add script /var/cpanel/hooks/fixincomingsuspend.php
    Then finally edit the file:

    /usr/local/cpanel/etc/exim/acls/ACL_RECIPIENT_BLOCK/custom_end_recipient

    (this file may be empty for you, that's fine) so that it includes:

    Code:
      deny condition = ${if eq{${lookup{${lc:$local_part@$domain}}lsearch{/etc/suspended_incoming}{1}{0}}}{1}}
      message = Mail to ${lc:$local_part@$domain} has been suspended
      log_message = Mail to ${lc:$local_part@$domain} has been suspended
    Save the file.

    Rebuild the Exim configuration:

    Code:
    /scripts/buildeximconf
    and restart Exim

    Code:
    /scripts/restartsrv_exim


    Now when you suspend incoming mail for an account that email address will be added to the file /etc/suspended_incoming

    When someone tries to send an email to that email address, the exim configuration will check /etc/suspended_incoming for the email address at the RCPT TO stage. If it is found to be in the /etc/suspended_incoming file, the SMTP transaction is denied and does not continue.

    The hook script (/var/cpanel/hooks/fixincomingsuspend.php) adds and removes these email addresses to the /etc/suspended_incoming file as end-users Suspend and Unsuspend incoming mail for an email account.


    This is not necessarily all well written, it's basically meant to be used as a proof of concept for how this should be done properly.

    This still doesn't fix the fact that fail should never be used in filter files (/etc/vfilters/example.tld or /home/user/etc/example.tld/email/filter). This will alleviate the problem of having incoming email suspension code in /home/user/etc/example.tld/email/filter because the Exim configuration code will stop those messages before they are ever accepted and the /home/user/etc/example.tld/email/filter code has a chance to run.

    This will not apply to email accounts that already have incoming mail suspended. You would need to manually add those email accounts to /etc/suspended_incoming.
     

    Attached Files:

    Infopro likes this.
  7. cPBrett

    cPBrett cPanel Developer
    Staff Member

    Joined:
    Jul 2, 2014
    Messages:
    4
    Likes Received:
    1
    Trophy Points:
    1
    cPanel Access Level:
    Root Administrator
    Thanks for the information, sparek-3. We're working on an improvement here, and I wanted to share with you the current line of thinking. Any feedback would be appreciated. In etc/exim/acls/ACL_RECIPIENT_BLOCK/default_recipient we're currently testing:
    Code:
      deny
      condition = ${if exists {${extract{5}{::}{${lookup passwd{${lookup{$domain}lsearch{/etc/userdomains}{$value}}}{$value}}}}/etc/\.$local_part\@$domain\.suspended_incoming}}
      message = Mail to ${lc:$local_part@$domain} has been suspended
      log_message = Mail to ${lc:$local_part@$domain} has been suspended
    
    This is leveraging the pre-existence of a $HOME/etc/.$local_part@$domain.suspended_incoming "dot" file (in addition to the generated filter) for each email address that has incoming mail suspended.

    We want to hear what y'all think.

    Cheers,
    Brett
     
    mtindor likes this.
  8. sparek-3

    sparek-3 Well-Known Member

    Joined:
    Aug 10, 2002
    Messages:
    1,381
    Likes Received:
    23
    Trophy Points:
    38
    cPanel Access Level:
    Root Administrator
    Bravo if you created that condition line! Exim conditionals are always difficult for me to read, much less create. I always misplace a { or don't have a } in the right place.

    That said, I didn't check this to see if it actually works. But the gist of it looking in $HOME/etc/.$local_part@$domain.suspended_incoming is probably a good idea. This way you can avoid having to run escalated privileges, which is what I had to do in my hook script.

    So basically you would just have to change the hook to create the $HOME/etc/.$local_part@$domain.suspended_incoming file or add that into the core when a cpanel user suspends an email account.

    I like it!
     
    cPBrett likes this.
  9. cPBrett

    cPBrett cPanel Developer
    Staff Member

    Joined:
    Jul 2, 2014
    Messages:
    4
    Likes Received:
    1
    Trophy Points:
    1
    cPanel Access Level:
    Root Administrator
    Awesome. Thanks for the quick feedback!
     
  10. sparek-3

    sparek-3 Well-Known Member

    Joined:
    Aug 10, 2002
    Messages:
    1,381
    Likes Received:
    23
    Trophy Points:
    38
    cPanel Access Level:
    Root Administrator
    Actually I suppose $HOME/etc/.$local_part@$domain.suspended_incoming is already created. I really hadn't paid that much attention. So yea, just adding the code into the exim configuration will accomplish all that needs to be done.

    I definitely like this better than failing a message after it has been accepted.

    Is $local_part and $domain automatically translated to lowercase in the condition? That might be my only question.
     
    mtindor likes this.
  11. cPanelKenneth

    cPanelKenneth cPanel Development
    Staff Member

    Joined:
    Apr 7, 2006
    Messages:
    4,458
    Likes Received:
    22
    Trophy Points:
    38
    cPanel Access Level:
    Root Administrator
    The .suspended_incoming dot file is already created when incoming email is suspended for an account. We're just changing Exim's behavior to reject at RCPT time based upon presence of that file.

    I do believe both $local_part and $domain are normalized to lowercase, since we use those same variables all over the place in Exim's ACLs.

    Also, I want to thank you, sparek-3, for your initial research on this which put us quickly on the right path.
     
    mtindor and Infopro like this.
Loading...

Share This Page