Sending emails from Julia using sendmail

Hello, which is the simplest way to send basic text emails from a julia script in a server that already has sendmail (PostFix sendmail interface) but without setting up a SMTP server (i.e. without https://github.com/aviks/SMTPClient.jl) ?

I am trying with:

sendEmailCmd = `sendmail \-t \< testEmail`
run(sendEmailCmd)

where testEmail is a file with:

To: myTestAddress@gmail.com
From: myFromAdress@myServer.org
Subject: One-line subject

This is the content of the email.

(would be better if it could be just a string in Julia, so I don’t need to save it to disk)

But it stucks and it doesn’t work (on the command line it works).

If I then I type mail, I notice an undelivered mail message where the key point is:

<testEmail@myServer.org> (expanded from <testEmail>): unknown user:
    "testemail"

<"<"@myServer.org> (expanded from <"<">): unknown user: "<"

For pipes in Julia, you explicitly need to use pipeline, <, > and | don’t work in commands yet, like they do in Bash. You probably want:

sendEmailCmd = pipeline("testEmail", `sendmail -t`)
run(sendEmailCmd)
2 Likes

Thank you, it works.
Is there a way I can replace the file testEmail with a string composed in Julia ?

Yes, you can use an IOBuffer in the pipeline like so:

message = """
       To: myTestAddress@gmail.com
       From: myFromAdress@myServer.org
       Subject: One-line subject

       This is the content of the email."""
sendEmailCmd = pipeline(IOBuffer(message), `sendmail -t`)
run(sendEmailCmd)

uhg, I got a MethodError…

julia> message = """
              To: myTestAddress@gmail.com
              From: myFromAdress@myServer.org
              Subject: One-line subject

              This is the content of the email."""
"To: myTestAddress@gmail.com\nFrom: myFromAdress@myServer.org\nSubject: One-line subject\n\nThis is the content of the email."

julia> sendEmailCmd = pipeline(IOBuffer(message), `sendmail -t`)
pipeline(`sendmail -t`, stdin=IOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=120, maxsize=Inf, ptr=1, mark=-1))

julia> run(sendEmailCmd)
ERROR: MethodError: no method matching rawhandle(::Base.GenericIOBuffer{Array{UInt8,1}})
Closest candidates are:
  rawhandle(::RawFD) at process.jl:149
  rawhandle(::Base.DevNull) at process.jl:148
  rawhandle(::Base.Filesystem.File) at filesystem.jl:69
  ...
Stacktrace:
 [1] _jl_spawn(::String, ::Array{String,1}, ::Cmd, ::Tuple{Base.GenericIOBuffer{Array{UInt8,1}},RawFD,RawFD}) at ./process.jl:345
 [2] (::getfield(Base, Symbol("##493#494")){Cmd})(::Tuple{Base.GenericIOBuffer{Array{UInt8,1}},RawFD,RawFD}) at ./process.jl:509
 [3] setup_stdio(::getfield(Base, Symbol("##493#494")){Cmd}, ::Tuple{Base.GenericIOBuffer{Array{UInt8,1}},RawFD,RawFD}) at ./process.jl:490
 [4] #_spawn#492(::Nothing, ::Function, ::Cmd, ::Tuple{Base.GenericIOBuffer{Array{UInt8,1}},RawFD,RawFD}) at ./process.jl:508
 [5] (::getfield(Base, Symbol("#kw##_spawn")))(::NamedTuple{(:chain,),Tuple{Nothing}}, ::typeof(Base._spawn), ::Cmd, ::Tuple{Base.GenericIOBuffer{Array{UInt8,1}},RawFD,RawFD}) at ./none:0
 [6] #_spawn#489(::Nothing, ::Function, ::Base.CmdRedirect, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:398
 [7] _spawn at ./process.jl:398 [inlined]
 [8] #run#503(::Bool, ::Function, ::Base.CmdRedirect) at ./process.jl:662
 [9] run(::Base.CmdRedirect) at ./process.jl:661
 [10] top-level scope at none:0

That does seem odd. Could you try if

run(pipeline(IOBuffer(message), `cat`))

works on your machine? What is your os, maybe the output of versioninfo() can give some more clues. If you’re running Julia 1.0, it may be the same as this issue. Does

pipeline(`sendmail -t`, stdin=IOBuffer(message))

work?

Yes… I was looking as well… I think this has to do with this feature request implemented on master in this merge of 7 Dec 2018, so it should works on recent Julias, but I have 1.0.3.

pipeline(sendmail -t, stdin=IOBuffer(message)) has been merged in February 20189, so it also doesn’t work with Julia 1.0… ok, I’ll update Julia on the server…

UPDATE: I can report the suggestions given by @ simeonschaub (i.e. sendEmailCmd = pipeline(IOBuffer(message), sendmail -t) or run(pipeline(IOBuffer(message), cat))) works with Julia 1.1 (but not with Julia 1.0.4). Thank you again.

Hi,
Jumping in on this thread.,
Is there a nice way to encode a graphics file and send it as an attachment with this library?

Thanks for any pointer and best wishes
Eric

There are multiple ways to do this proposed in this StackOverflow thread:

https://unix.stackexchange.com/questions/223636/sendmail-attachment/223650

I would just check, if any of these proposed alternatives are installed on your system.

1 Like

Thanks @simeonschaub!
Yes, I was wondering if there was a higher level way than the method referred to here.
So will build up the base64 and separators and send with SMTPClient.jl
:slight_smile: