Compare commits

...

10 commits

6 changed files with 168 additions and 73 deletions

32
COPYING
View file

@ -1,25 +1,13 @@
Copyright (c) 2024 Jeremy Baxter. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -20,5 +20,6 @@ clean:
install:
install -Dm755 mal "${DESTDIR}${PREFIX}"/bin/mal
install -Dm644 mal.1 "${DESTDIR}${PREFIX}"/share/man/man1/mal.1
.PHONY: all clean install

13
README Normal file
View file

@ -0,0 +1,13 @@
mal sends mail to one or more recipients, through information passed
on its command line. Read COPYING for information on redistribution.
* Building
With ldc and libcurl installed, run:
$ make
# make install # to install
Documentation is provided in the man page.
Written by Jeremy Baxter <jeremy@reformers.dev>

View file

@ -1,45 +0,0 @@
mal sends an email to one or more recipients, through information passed
on its command line. Read COPYING for information on redistribution.
## compilation
Install ldc and curl, and run make. To install the binary systemwide,
run make install after compiling.
## usage
Send an email from you@example.org to joe@example.org
with the message body "hello!":
mal -m 'hello!' -t joe@example.org -P password123 you@example.org
Read the message body from a file instead:
mal -M mesgfile -t joe@example.org -P password123 you@example.org
Send the message to multiple recipients:
mal -M mesgfile -t joe@example.org -t jane@example.org -P password123 \
you@example.org
If SSL is not working properly, use an insecure connection with -k:
mal -k -m 'hello!' -t joe@example.org -P password123 \
you@example.org
To send a message from an address with a plus in it, manually specify
the username with -u:
mal -m 'hello!' -t joe@example.org -u you -P password123 \
you+malbot@example.org
CC john@example.org:
mal -m 'hello!' -t joe@example.org -H 'Cc: <john@example.org>' -P password123 \
you@example.org
Read a quick usage example:
mal
Man pages hopefully coming soon.

134
mal.1 Normal file
View file

@ -0,0 +1,134 @@
.Dd $Mdocdate: June 17 2024 $
.Dt MAL 1
.Os
.Sh NAME
.Nm mal
.Nd send mail
.Sh SYNOPSIS
.Nm mal
.Bk -words
.Op Fl ksV
.Op Fl a Ar server
.Op Fl F Ar fqdn
.Op Fl H Ar header
.Op Fl n Ar name
.Op Fl P Ar passphrase
.Op Fl p Ar port
.Op Fl S Ar subject
.Op Fl t Ar toaddress
.Op Fl u Ar user
.No { Ns Fl M Ar file | Fl m Ar message Ns }
.Ar fromaddress
.Ek
.Sh DESCRIPTION
.Nm
sends mail to one or more recipients,
whose addresses are specified by the
.Fl t
option.
The mail is sent from the address specified by
.Ar fromaddress ,
and if
.Fl t
is not given, mail will be sent back to the sender's address.
The
.Fl P
option specifies a passphrase.
.Pp
The options are as follows:
.Bl -tag -width 123456
.It Fl a Ar server
Specify the address of the SMTP server to connect to.
By default this is the domain segment of
.Ar fromaddress .
.It Fl F Ar fqdn
Specify the FQDN to pass to the SMTP server.
By default this is set to the system's hostname with
.Dq .local
appended to the end.
.It Fl H Ar header
Add a header to the request.
This is necessary if you would like to, for instance
CC someone in your mail.
See the
.Sx EXAMPLES
section below for an example using this option.
.It Fl k
Use an insecure SMTP connection.
By default
.Nm mal
will attempt to connect with secure SMTPS,
but if your server doesn't support this you should use
.Fl k .
See also
.Fl s
for forcing a secure connection.
.It Fl M Ar file
Specify a file which contains the message's contents.
.It Fl m Ar message
Specify a message on the command line.
.It Fl n Ar name
Specify a real name to identify the sender of the mail.
.It Fl P Ar passphrase
Specify a passphrase to use to authenticate the SMTP user.
Without this option no authentication will be used.
.It Fl p Ar port
Override the SMTP server port.
By default this will be
465 for SMTPS servers
or 587 for plain SMTP servers.
See also the
.Fl k
flag.
.It Fl S Ar subject
Specify the subject line of the mail.
.It Fl s
Force a secure SMTPS connection.
This is the default and only required if you want to override
a previous
.Fl k
flag.
.It Fl t Ar toaddress
Specify a recipient for the mail.
If you would like to CC someone instead,
see the
.Fl H
option.
If this option is not given,
the mail will be sent to the sender's address.
This option can be specified multiple times
to send email to multiple recipients.
.It Fl u Ar user
Specify the SMTP user.
By default this is the sender's address.
.It Fl V
Print the version number and exit.
.El
.Sh EXAMPLES
Send an email to
.Mt joe@example.org
with the message
.Dq Hello :
.Pp
.Dl mal -m Hello -t joe@example.org -P mypasswd you@example.org
.Pp
Read the message from the file
.Dq mesg
instead:
.Pp
.Dl mal -M mesg -t joe@example.org -P mypasswd you@example.org
.Pp
CC
.Mt jane@example.org :
.Pp
.Dl mal -M mesg -t joe@example.org -H 'Cc: <jane@example.org>' -P mypasswd you@example.org
.Pp
.Sh AUTHORS
.An Jeremy Baxter Aq Mt jeremy@baxters.nz
.Sh BUGS
.Pp
Currently known bugs or issues can be found at the tracker:
.Lk https://todo.sr.ht/~jeremy/mal
.Pp
If you happen to find a bug,
please report it to me using my address above.

16
mal.d
View file

@ -71,10 +71,9 @@ main(string[] args)
fqdn = hostName() ~ ".local";
mailHeaders = toAddrs = [];
subject = "";
useSmtps = true;
authUser = message = messageFile = passPhrase =
realName = serverAddr = serverPort = null;
realName = serverAddr = serverPort = subject = null;
try {
import std.getopt : config;
@ -120,7 +119,7 @@ main(string[] args)
}
if (showVersion) {
writeln("mal version 0.0.0");
writeln("mal version 1.0");
return 0;
}
@ -128,12 +127,12 @@ main(string[] args)
stderr.writeln(
`usage: mal [-ksV] [-a server] [-F fqdn] [-H header] [-n name]
[-P passphrase] [-p port] [-S subject] [-t toaddress]
[-u username] {-M messagefile | -m message} fromaddress`);
[-u user] {-M file | -m message} fromaddress`);
return 1;
}
enforceDie(message || messageFile,
"email messsage has to be provided through -M or -m");
"a message has to be provided with -M or -m");
enforceDie(!(message && messageFile),
"flags -M and -m cannot both be supplied in one invocation");
@ -153,7 +152,8 @@ main(string[] args)
addr = "<" ~ addr ~ ">";
}
authUser = authUser ? authUser : fromStatus.localPart;
/* https://todo.sr.ht/~jeremy/mal/2 */
authUser = authUser ? authUser : fromAddr;
protocol = useSmtps ? "smtps" : "smtp";
serverAddr = serverAddr ? serverAddr : fromStatus.domainPart;
serverPort = serverPort ? serverPort : useSmtps ? "465" : "587";
@ -162,6 +162,10 @@ main(string[] args)
warn("warning: -P not supplied, using empty passphrase");
passPhrase = "";
}
if (!subject) {
warn("warning: -S not supplied, using empty subject line");
subject = "";
}
try {
messageBuf =