skip to Main Content

I’m researching imap and smtp and found interesting things …

Messages are received and sent using an endpoint / socket TCP / IP over SSL or TLS, interestingly php is able to create a socket and receive and send data through it, well, I could modify the domain’s dns and point to the endpoint . The main IMAP commands are LOGIN and SELECT, of course, there are others, but these are more interesting, this tutorial shows how an IMAP server works:

https://www.toptal.com/php/building-an-imap-email-client-with-php

based on this it is possible to imitate the server and easily replace it, a database and some authentication techniques are essential, it is not difficult to find "login" in a header, it is also possible to search for words in texts, therefore the need for a command line terminal is no longer essential, I just need to know what the customer does, validate and who knows how to deliver.

There are probably theses contrary to mine, suggestions on how to use a Devecot or not reinvent the wheel, I already have a server, but it is useless, I need something based on the web for greater integration, I could use one of these APIS from cpanel, but no , is not what I want.

What I’m trying to understand here is how this transaction is made, see a shipping code:

// The message
$message = "Line 1rnLine 2rnLine 3";

// In case any of our lines are larger than 70 characters, we should use wordwrap()
$message = wordwrap($message, 70, "rn");

// Send
mail('[email protected]', 'My Subject', $message);

It is important to note that just because the email is accepted for
delivery, it does not mean that the email will reach the expected
destination. https://www.php.net/manual/en/function.mail.php

It doesn’t make sense, but ok, let’s consider that he went through dozens of servers and one of them was in a bad mood, by the way, which is nothing new, so he decided to disappear with the email and that’s it. The most confusing thing here is that emails go through one or more transfer agents and these agents can appeal the message, they even read to see if it is in compliance, privacy has been eliminated in this process … so in practice there is a supervisor who receives and if it is in accordance with your criteria, search and delivery to the recipient, plus the documentation talks a lot about "commands", "injection of commands", after all
1 – How do these emails reach the recipient server?
2 – Everything here is a command or does it have text too?
3 – How can I capture these requests?
For example: Server A sends to Server B (‘Agent’) a message addressed to Server C, so Server C needs to process it and reply that it accepts the message, at the same time the documentation insists on "commands" talking about injection command, which means that Server B will inject commands into server C, so from now on it’s no longer http, now it should be something like ssh or maybe telnet (hopefully not), where did the http header end up?

$headers = array(
    'From' => '[email protected]',
    'Reply-To' => '[email protected]',
    'X-Mailer' => 'PHP/' . phpversion()
);

2

Answers


  1. Chosen as BEST ANSWER

    I found a less painful way to do this, on github there are 6 packages that intend to act as an email receiver, one of them follows the same logic as mine, creates a socket and tries to understand what the customer is trying to do, validate and deliver if applicable, making a filter based on a blacklist, here is using a very simple json configuration file, this is very good for those working with a javascript framework, in my case in particular it will not be useful, I will have to cut it it in pieces to make it the way I’m idealizing, but it will help those who need it in the future, it’s very small, it has 3 php files and 1 json file, it also has another more documented json file.

    PHPMailServ An SMTP email receiver server, written in PHP. https://github.com/timmyRS/PHPMailServ

    It specifies that you need to download the project, provide permission 777 and run this line in the terminal: screen php run.php

    The reason is very simple, you need to start the socket before making the request, once this is done, it will be available at http://localhost port 25

    Although there are controversies, you can specify the port you want, it is now standard to use 585 to send and port 25 to receive, minimally modern email clients should provide the option of advanced configuration, but if this is not possible, there are hundreds of php libraries to access the mailbox via imap and pop3, in addition many of the email clients use port discovery, one of which is gmail.

    run.php

    <?php
    if(empty($argv))
    {
        die("ERROR: Please run this script using the `php run.php`-command in your shell.");
    }
    echo "Initiating...n";
    set_time_limit(0);
    error_reporting(E_ALL);
    require "src/Client.class.php";
    
    $config=json_decode(file_get_contents("config.json"),true);
    if($config==null)
    {
        if(function_exists("json_last_error_msg"))
        {
            die("ERROR: Couldn't load config.json - ".json_last_error_msg()."n");
        } else
        {
            die("ERROR: Couldn't load config.json - JSON error #".json_last_error()."n");
        }
    }
    
    require "src/EmailAddr.class.php";
    if(empty($config["users"]))
    {
        die("ERROR: `users` is not defined in config.jsonn");
    }
    if(empty($config["motd"]))
    {
        $config["motd"] = "You've reached a PHPMailServ server. (Ohh no!)";
    }
    if(empty($config["hostname"]))
    {
        $config["hostname"] = "localhost";
    }
    if(empty($config["size"]))
    {
        $config["size"] = 10240000;
    }
    if(empty($config["sender_blacklist"]))
    {
        $config["sender_blacklist"] = ["wildcard@localhost"];
    }
    $addrs = [];
    foreach($config["users"] as $name => $data)
    {
        $arr = explode("@", $name);
        if(count($arr) == 2)
        {
            $addr = new EmailAddr($name, $data);
            array_push($addrs, $addr);
        } else
        {
            echo "Skipped invalid user {$name}n";
        }
    }
    unset($config["users"]);
    echo "Loaded ".count($addrs)." addresses.n";
    
    $sSocket = socket_create(AF_INET, SOCK_STREAM, 0) or die();
    socket_set_option($sSocket, SOL_SOCKET, SO_REUSEADDR, 1) or die();
    socket_bind($sSocket, "0.0.0.0",25) or die();
    socket_listen($sSocket) or die();
    echo "Listening on <0.0.0.0:25>...n";
    
    $connections = [];
    while(true)
    {
        $sReader = [$sSocket];
        foreach($connections as $x => $c)
        {
            if($c->closed)
            {
                unset($connections[$x]);
                $c->log("~ disconnected");
                continue;
            }
            array_push($sReader, $c->socket);
        }
        $null = null;
        $num_changed_sockets = socket_select($sReader, $null, $null, null);
        if($num_changed_sockets === false)
        {
            echo "ERROR: ".socket_strerror(socket_last_error())."n";
            exit;
        }
        if($num_changed_sockets > 0)
        {
            if(in_array($sSocket, $sReader))
            {
                $c = new Client(socket_accept($sSocket));
                array_push($connections, $c);
                $c->log("~ connected");
                $c->send("220 ".$config["motd"]);
            } else
            {
                foreach($connections as $c)
                {
                    if(in_array($c->socket, $sReader))
                    {
                        $data = socket_read($c->socket, 1);
                        if($data)
                        {
                            if($data != "")
                            {
                                if($data == "n")
                                {
                                    $c->line = trim($c->line);
                                    if($c->line != "")
                                    {
                                        $c->log("> ".$c->line)->handle()->line="";
                                    }
                                } else if($data != "r")
                                {
                                    $c->line .= $data;
                                }
                            }
                        } else
                        {
                            $c->disconnect();
                        }
                    }
                }
            }
        }
    }
    ?>
    

    Correction: port 25 was closed in some countries due to the number of spam, the most used ports in SMTP are 585, 587 and 465


  2. It looks like you are missing a basic understanding of how mail delivery works.

    The php mail() function invokes a sendmail program, usually configured by the system administrator, that allows you to send emails. The sendmail program is responsible to do the delivery in this case. There are several libs out there that doesn’t rely on sendmail and sends emails directly using sockets. The link you provided is one of such libs. Note that those libs are clients, not servers. They don’t receive mail, only send.

    To be able to receive emails using pure php you would need to create a socket that listens in the default email ports. This server must be able to understand and reply to the commands described in the SMTP protocol.

    HTTP headers have nothing to do with email delivery. The commands you mentioned are keywords following a set of rules and procedures described in a protocol for transmitting data.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search