Node.js sendmail without library
I'm sick of being fucked by sudden API changes by 3rd party library. So here's a 70 lines of codes to send email by using Socket.

* This setup is good for when you have a centralized local relay such as postfix or exim4.
* Does not support attachments, it's only 70 lines of codes and I'm sure you can modify it to suit your needs.
"use strict";
const net = require( "net" );
const [ HOST, PORT ] = "localhost:25000".split( ":" );
const MAIL_FROM = "noreply@example.com";

const Sendmail = ( address, senderName, subject, mesg, callback ) => {

    subject = subject.replaceAll( "\r", "" ).replaceAll( "\n", "" );
    mesg = mesg.replaceAll( "\r", "" ).replaceAll( "\n.", "\n.." );
    senderName = senderName.replaceAll( "\"", "\\\"" ).replaceAll( "'", "\\'" );

    var _mesgs = [
        [
            ( x ) => ( x.indexOf( "220 " ) === 0 )
            , ""
        ]
        , [
            ( x ) => ( x.indexOf( "250-" ) === 0 )
            , `EHLO ${HOST}`
        ]
        , [
            ( x ) => ( x == "250 2.1.0 Ok" )
            , `MAIL FROM: <${MAIL_FROM}>`
        ]
        , [
            ( x ) => ( x == "250 2.1.5 Ok" )
            , `RCPT TO: ${address}`
        ]
        , [
            ( x ) => ( x.indexOf( "354 End data with" ) === 0 )
            , `DATA`
        ]
        , [
            ( x ) => ( x.indexOf( "250 2.0.0 Ok" ) === 0 )
            , `From: "${senderName}"<${MAIL_FROM}> \nTo: ${address}\nSubject: ${subject}\n\n${mesg}\r\n.\r`
        ]
        , [
            ( x ) => ( x.indexOf( "221 2.0.0" ) === 0 )
            , `QUIT`
        ]
    ];
    
    var i = 0, l = _mesgs.length;
    var _error = new Error( "Unknown error occurred" );
    
    var sock = net.connect( PORT, HOST, () => {
        console.log( `CONNECTED TO: ${HOST}:${PORT}` );
    });

    sock.addListener( "error", ( e ) => { _error = e; } );
    sock.addListener( "data", x => {
        x = x.toString().trim();

        var [ expect, data ] = _mesgs[i];

        console.log( `SMTP: < ${x}` );

        if( expect( x ) )
        {
            if( ( i + 1 ) < l )
            {
                [ expect, data ] = _mesgs[++i];
                console.log( `SMTP: > ${data}` );
                sock.write( data + "\r\n" );
            }
        }
        else
        {
            _error = new Error( `${x}: "${data}"` );
            sock.destroy( _error );
        }
    });


    sock.addListener( "close", ( hadError ) => {
        console.log( "Connection closed" );

        if( hadError )
        {
            callback( _error );
        }
        else
        {
            callback();
        }
    });
};

_mesgs[][]

The lambda ( x ) => ( x == "250..." ) is the expected return from the server. Following is the data to write to the server. Use the output to craft your on lambda expect.

Caveats

* Only use this to connect to a local mail server ( e.g. exim4 / postfix ) since this does not support TLS or authentication. Use a library if you want those features.
* If the mail content starts with . then it'll go funny. You can fix this easily by replacing the starting . with ... So I'm not going to fix this here since all my mail does not start with .

Usage

Sendmail(
    "test@example.com", "My Sender Name"
    , "Test Mail Subject"
    , "Test Mail Content"
    , ( err ) => {
        if( err )
            console.error( err );
    } );

Outputs

CONNECTED TO: localhost:25000
SMTP: < 220 postfix-69676b6b47-546sn.localdomain ESMTP Postfix
SMTP: > EHLO localhost
SMTP: < 250-postfix-69676b6b47-546sn.localdomain
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
SMTP: > MAIL FROM: <noreply@example.com>
SMTP: < 250 2.1.0 Ok
SMTP: > RCPT TO: test@example.com
SMTP: < 454 4.7.1 <test@example.com>: Relay access denied
Connection closed
Error: 454 4.7.1 <test@example.com>: Relay access denied: "RCPT TO: test@example.com"

Debug logs from this blog
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: > MAIL FROM: <noreply@astropenguin.net>
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: < 250 2.1.0 Ok
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: > RCPT TO: tgckpg@gmail.com
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: < 250 2.1.5 Ok
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: > DATA
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: < 354 End data with <CR><LF>.<CR><LF>
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: > From: "Penguin\'s Blog // Rosemary"<noreply@astropenguin.net>
To: tgckpg@gmail.com
Subject: Test Mail Subject

Test Mail Content
.
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: < 250 2.0.0 Ok: queued as 588608E10A0
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: > QUIT
[ M:1001 ] [ 2022-09-02 08:32:06 ] SMTP: < 221 2.0.0 Bye
[ M:1001 ] [ 2022-09-02 08:32:06 ] Connection closed
Profile picture
斟酌 鵬兄
Fri Sep 02 2022 07:57:53 GMT+0000 (Coordinated Universal Time)
Last modified: Fri Sep 02 2022 09:00:03 GMT+0000 (Coordinated Universal Time)
Comments
No comments here.
Do you even comment?
website: 
Not a valid website
Invalid email format
Please enter your email
*Name: 
Please enter a name
Submit
抱歉,Google Recaptcha 服務被牆掉了,所以不能回覆了