Send email: Difference between revisions

From Rosetta Code
Content added Content deleted
(added omit from ML/I)
m ({{omit from|Openscad}})
Line 765: Line 765:


{{omit from|ML/I}}
{{omit from|ML/I}}
{{omit from|Openscad}}
{{omit from|PARI/GP}}
{{omit from|PARI/GP}}
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} {{omit from|JavaScript}} <!-- Does not have network access. -->
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} {{omit from|JavaScript}} <!-- Does not have network access. -->

Revision as of 21:51, 17 August 2011

Task
Send email
You are encouraged to solve this task according to the task description, using any language you may know.

Write a function to send an email. The function should have parameters for setting From, To and Cc addresses; the Subject, and the message text, and optionally fields for the server name and login details.

  • If appropriate, explain what notifications of problems/success are given.
  • Solutions using libraries or functions from the language are preferred, but failing that, external programs can be used with an explanation.
  • Note how portable the solution given is between operating systems when multi-OS languages are used.

(Remember to obfuscate any sensitive data used in examples)

Ada

Library: AWS

<lang Ada>with AWS.SMTP, AWS.SMTP.Client, AWS.SMTP.Authentication.Plain; with Ada.Text_IO; use Ada, AWS;

procedure Sendmail is

  Status : SMTP.Status;
  Auth : aliased constant SMTP.Authentication.Plain.Credential :=
     SMTP.Authentication.Plain.Initialize ("id", "password");
  Isp : SMTP.Receiver;

begin

  Isp :=
     SMTP.Client.Initialize
       ("smtp.mail.com",
        Port       => 5025,
        Credential => Auth'Unchecked_Access);
  SMTP.Client.Send
    (Isp,
     From    => SMTP.E_Mail ("Me", "me@some.org"),
     To      => SMTP.E_Mail ("You", "you@any.org"),
     Subject => "subject",
     Message => "Here is the text",
     Status  => Status);
  if not SMTP.Is_Ok (Status) then
     Text_IO.Put_Line
       ("Can't send message :" & SMTP.Status_Message (Status));
  end if;

end Sendmail; </lang>

AutoHotkey

ahk discussion

Library: COM.ahk

<lang autohotkey>sSubject:= "greeting" sText  := "hello" sFrom  := "ahk@rosettacode" sTo  := "whomitmayconcern"

sServer  := "smtp.gmail.com" ; specify your SMTP server nPort  := 465 ; 25 bTLS  := True ; False inputbox, sUsername, Username inputbox, sPassword, password

COM_Init() pmsg := COM_CreateObject("CDO.Message") pcfg := COM_Invoke(pmsg, "Configuration") pfld := COM_Invoke(pcfg, "Fields")

COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/sendusing", 2) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout", 60) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/smtpserver", sServer) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/smtpserverport", nPort) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/smtpusessl", bTLS) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/sendusername", sUsername) COM_Invoke(pfld, "Item", "http://schemas.microsoft.com/cdo/configuration/sendpassword", sPassword) COM_Invoke(pfld, "Update")

COM_Invoke(pmsg, "Subject", sSubject) COM_Invoke(pmsg, "From", sFrom) COM_Invoke(pmsg, "To", sTo) COM_Invoke(pmsg, "TextBody", sText) COM_Invoke(pmsg, "Send")

COM_Release(pfld) COM_Release(pcfg) COM_Release(pmsg) COM_Term()

  1. Include COM.ahk</lang>

Delphi

<lang Delphi> procedure SendEmail; var

 msg: TIdMessage;
 smtp: TIdSMTP;

begin

 smtp := TIdSMTP.Create;
 try
   smtp.Host := 'smtp.server.com';
   smtp.Port := 587;
   smtp.Username := 'login';
   smtp.Password := 'password';
   smtp.AuthType := satNone;
   smtp.Connect;
   msg := TIdMessage.Create(nil);
   try
     with msg.Recipients.Add do begin
       Address := 'doug@gmail.com';
       Name := 'Doug';
     end;
     with msg.Sender do begin
       Address := 'fred@server.com';
       Name := 'Fred';
     end;
     msg.Subject := 'subj';
     msg.Body.Text := 'here goes email message';
     smtp.Send(msg);
   finally
     msg.Free;
   end;
 finally
   smtp.Free;
 end;

end; </lang>

Factor

This one uses the build-in SMTP vocabulary. Note that 'to' and 'cc' need to be arrays of strings containing an email address.

<lang Factor> USING: kernel accessors smtp io.sockets namespaces ; IN: learn

send-mail ( from to cc subject body -- )
   "smtp.gmail.com" 587 <inet> smtp-server set
   smtp-tls? on
   "noneofyourbuisness@gmail.com" "password" <plain-auth> smtp-auth set
   <email>
       swap >>from
       swap >>to
       swap >>cc
       swap >>subject
       swap >>body
   send-email ;</lang>

Fantom

There's a built-in Email library, which will work on the JVM, CLR and Javascript runtimes. Errors are thrown if there is a problem with the protocol or the network.

<lang fantom> using email

class Mail {

 // create a client for sending email - add your own host/username/password
 static SmtpClient makeClient ()
 {
   client := SmtpClient
   {
     host     = "yourhost"
     username = "yourusername"
     password = "yourpassword"
   }
   return client
 }
 public static Void main()
 {
   // create email
   email := Email
   {
     to = ["to@addr"]
     from = "from@addr"
     cc = ["cc@addr"]
     subject = test"
     body = TextPart { text = "test email" }
   }
   // create client and send email
   makeClient.send (email)
 }

} </lang>

Go

A full little command-line program that can be used to send simple e-mails. Uses the built-in smtp package. Supports TLS connections.

<lang go>package main

import( "os" "fmt" "flag" "smtp" "bufio" "bytes" "strings" "io/ioutil" )

type Message struct { From string To []string Cc []string Subject string Content string }

func (m Message)Bytes() (r []byte) { to := strings.Join(m.To, ",") cc := strings.Join(m.Cc, ",")

r = append(r, []byte("From: " + m.From + "\n")...) r = append(r, []byte("To: " + to + "\n")...) r = append(r, []byte("Cc: " + cc + "\n")...) r = append(r, []byte("Subject: " + m.Subject + "\n\n")...) r = append(r, []byte(m.Content)...)

return }

func (m Message)Send(host string, port int, user, pass string) (err os.Error) { err = check(host, user, pass) if err != nil { return }

err = smtp.SendMail(fmt.Sprintf("%v:%v", host, port), smtp.PlainAuth("", user, pass, host), m.From, m.To, m.Bytes(), )

return }

func check(host, user, pass string) (os.Error) { if host == "" { return os.NewError("Bad host") } if user == "" { return os.NewError("Bad username") } if pass == "" { return os.NewError("Bad password") }

return nil }

func main() { var flags struct { host string port int user string pass string } flag.StringVar(&flags.host, "host", "", "SMTP server to connect to") flag.IntVar(&flags.port, "port", 587, "Port to connect to SMTP server on") flag.StringVar(&flags.user, "user", "", "Username to authenticate with") flag.StringVar(&flags.pass, "pass", "", "Password to authenticate with") flag.Parse()

err := check(flags.host, flags.user, flags.pass) if err != nil { flag.Usage() os.Exit(1) }

bufin := bufio.NewReader(os.Stdin)

fmt.Printf("From: ") from, err := bufin.ReadString('\n') if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } from = strings.Trim(from, " \t\n\r")

var to []string for { fmt.Printf("To (Blank to finish): ") tmp, err := bufin.ReadString('\n') if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } tmp = strings.Trim(tmp, " \t\n\r")

if tmp == "" { break }

to = append(to, tmp) }

var cc []string for { fmt.Printf("Cc (Blank to finish): ") tmp, err := bufin.ReadString('\n') if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } tmp = strings.Trim(tmp, " \t\n\r")

if tmp == "" { break }

cc = append(cc, tmp) }

fmt.Printf("Subject: ") subject, err := bufin.ReadString('\n') if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } subject = strings.Trim(subject, " \t\n\r")

fmt.Printf("Content (Until EOF):\n") content, err := ioutil.ReadAll(os.Stdin) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } content = bytes.Trim(content, " \t\n\r")

m := Message{ From: from, To: to, Cc: cc, Subject: subject, Content: string(content), }

fmt.Printf("\nSending message...\n") err = m.Send(flags.host, flags.port, flags.user, flags.pass) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) }

fmt.Printf("Message sent.\n") }</lang>

Java

<lang java5>import java.util.Properties;

import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.Message.RecipientType; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage;

/**

* Mail
*/

public class Mail {

/**
 * Session
 */
protected Session session;
/**
 * Mail constructor.
 * 
 * @param host Host
 */
public Mail(String host)
{
 Properties properties = new Properties();
 properties.put("mail.smtp.host", host);
 session = Session.getDefaultInstance(properties);
}
/**
 * Send email message.
 *
 * @param from From
 * @param tos Recipients
 * @param ccs CC Recipients
 * @param subject Subject
 * @param text Text
 * @throws MessagingException
 */
public void send(String from, String tos[], String ccs[], String subject,
       String text)
       throws MessagingException
{
 MimeMessage message = new MimeMessage(session);
 message.setFrom(new InternetAddress(from));
 for (String to : tos)
  message.addRecipient(RecipientType.TO, new InternetAddress(to));
 for (String cc : ccs)
  message.addRecipient(RecipientType.TO, new InternetAddress(cc));
 message.setSubject(subject);
 message.setText(text);
 Transport.send(message);
}

}</lang>

LotusScript

<lang Lotusscript>Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Set db = session.CurrentDatabase Set doc = New NotesDocument( db ) doc.Form = "Memo" doc.SendTo = "John Doe" doc.Subject = "Subject of this mail" Call doc.Send( False )</lang>

Lua

Using LuaSocket's SMTP module (from the documentation on that page):

<lang Lua>-- load the smtp support local smtp = require("socket.smtp")

-- Connects to server "localhost" and sends a message to users -- "fulano@example.com", "beltrano@example.com", -- and "sicrano@example.com". -- Note that "fulano" is the primary recipient, "beltrano" receives a -- carbon copy and neither of them knows that "sicrano" received a blind -- carbon copy of the message. from = "<luasocket@example.com>"

rcpt = {

 "<fulano@example.com>",
 "<beltrano@example.com>",
 "<sicrano@example.com>"

}

mesgt = {

 headers = {
   to = "Fulano da Silva <fulano@example.com>",
   cc = '"Beltrano F. Nunes" <beltrano@example.com>',
   subject = "My first message"
 },
 body = "I hope this works. If it does, I can send you another 1000 copies."

}

r, e = smtp.send{

 from = from,
 rcpt = rcpt, 
 source = smtp.message(mesgt)

} </lang>

Mathematica

Mathematica has the built-in function SendMail, example: <lang Mathematica>SendMail["From" -> "from@email.com", "To" -> "to@email.com",

"Subject" -> "Sending Email from Mathematica", "Body" -> "Hello world!", 
"Server" -> "smtp.email.com"]</lang>

The following options can be specified: <lang Mathematica>"To" "Cc" "Bcc" "Subject" "Body" "Attachments" "From" "Server" "EncryptionProtocol" "Fullname" "Password" "PortNumber" "ReplyTo" "ServerAuthentication" "UserName"</lang> Possible options for EncryptionProtocol are: "SSL","StartTLS" and "TLS". This function should work fine on all the OS's Mathematica runs, which includes the largest 3: Windows, Linux, Mac OSX.


OCaml

<lang ocaml>let h = Smtp.connect "smtp.gmail.fr";; Smtp.helo h "hostname";; Smtp.mail h "<john.smith@example.com>";; Smtp.rcpt h "<john-doe@example.com>";; let email_header = "\ From: John Smith <john.smith@example.com> To: John Doe <john-doe@example.com> Subject: surprise";; let email_msg = "Happy Birthday";; Smtp.data h (email_header ^ "\r\n\r\n" ^ email_msg);; Smtp.quit h;;</lang>

Perl

This subroutine throws an appropriate error if it fails to connect to the server or authenticate. It should work on any platform Perl does.

<lang perl>use Net::SMTP; use Authen::SASL;

 # Net::SMTP's 'auth' method needs Authen::SASL to work, but
 # this is undocumented, and if you don't have the latter, the
 # method will just silently fail. Hence we explicitly use
 # Authen::SASL here.

sub send_email

{my %o =
    (from => , to => [], cc => [],
     subject => , body => ,
     host => , user => , password => ,
     @_);
 ref $o{$_} or $o{$_} = [$o{$_}] foreach 'to', 'cc';
 my $smtp = new Net::SMTP($o{host} ? $o{host} : ())
     or die q(Couldn't connect to SMTP server);
 $o{password} and
    $smtp->auth($o{user}, $o{password}) ||
    die 'SMTP authentication failed';
 $smtp->mail($o{user});
 $smtp->recipient($_) foreach @{$o{to}}, @{$o{cc}};
 $smtp->data;
 $o{from} and $smtp->datasend("From: $o{from}\n");
 $smtp->datasend('To: ' . join(', ', @{$o{to}}) . "\n");
 @{$o{cc}} and $smtp->datasend('Cc: ' . join(', ', @{$o{cc}}) . "\n");
 $o{subject} and $smtp->datasend("Subject: $o{subject}\n");
 $smtp->datasend("\n$o{body}");
 $smtp->dataend;
 return 1;}</lang>

An example call:

<lang perl>send_email

  from => 'A. T. Tappman',
  to => ['suchandsuch@example.com', 'soandso@example.org'],
  cc => somebodyelse@example.net',
  subject => 'Important message',
  body => 'I yearn for you tragically.',
  host => 'smtp.example.com:587',
  user => 'tappman@example.com',
  password => 'yossarian';</lang>

If the host parameter is omitted, send_email falls back on the SMTP_Hosts defined in Net::Config. Hence, only two arguments are strictly necessary:

<lang perl>send_email

  to => 'suchandsuch@example.com',
  user => 'tappman@example.com';</lang>

PHP

<lang php>mail('hello@world.net', 'My Subject', "A Message!", "From: my@address.com");</lang>

PicoLisp

PicoLisp has a built-in 'mail' function. A minimal call would be <lang PicoLisp>(mail "localhost" 25 "me@from.org" "you@to.org" "Subject" NIL "Hello")</lang> Instead of "Hello" an arbitrary number of arguments may follow (possibly containing executable expressions) for the message body.

The 6th argument (here 'NIL') may specify a list of attachments.

Pike

Untested:

<lang pike>int main(){

  string to         = "some@email.add";
  string subject    = "Hello There.";
  string from       = "me@myaddr.ess";
  string msg        = "Hello there! :)";
  
  Protocols.SMTP.Client()->simple_mail(to,subject,from,msg);

}</lang>

PureBasic

<lang Purebasic>InitNetwork()

CreateMail(0, "from@mydomain.com", "This is the Subject")

SetMailBody(0, "Hello " + Chr(10) + "This is a mail !")

AddMailRecipient(0, "test@yourdomain.com", #PB_Mail_To)

AddMailRecipient(0, "test2@yourdomain.com", #PB_Mail_Cc)

If SendMail(0, "smtp.mail.com")

   MessageRequester("Information", "Mail correctly sent !")

Else

   MessageRequester("Error", "Can't sent the mail !")

EndIf</lang>

Python

The function returns a dict of any addresses it could not forward to; other connection problems raise errors.
Tested on Windows, it should work on all POSIX platforms.

<lang python>import smtplib

def sendemail(from_addr, to_addr_list, cc_addr_list,

             subject, message,
             login, password,
             smtpserver='smtp.gmail.com:587'):
   header  = 'From: %s\n' % from_addr
   header += 'To: %s\n' % ','.join(to_addr_list)
   header += 'Cc: %s\n' % ','.join(cc_addr_list)
   header += 'Subject: %s\n\n' % subject
   message = header + message
   
   server = smtplib.SMTP(smtpserver)
   server.starttls()
   server.login(login,password)
   problems = server.sendmail(from_addr, to_addr_list, message)
   server.quit()
   return problems</lang>

Example use: <lang python>sendemail(from_addr = 'python@RC.net',

         to_addr_list = ['RC@gmail.com'],
         cc_addr_list = ['RC@xx.co.uk'], 
         subject      = 'Howdy', 
         message      = 'Howdy from a python function', 
         login        = 'pythonuser', 
         password     = 'XXXXX')</lang>

Sample Email received:

Message-ID: <4a4a1e78.0717d00a.1ba8.ffcfdbdd@xx.google.com>
Date: Tue, 30 Jun 2009 22:04:56 -0700 (PDT)
From: python@RC.net
To: RC@gmail.com
Cc: RC@xx.co.uk
Subject: Howdy

Howdy from a python function

R

Library: tcltk
Library: gdata
Library: caTools

R does not have a built-in facility for sending emails though some code for this, written by Ben Bolker, is available here.

REBOL

<lang rebol>send user@host.dom "My message"</lang>

Ruby

Uses the

Library: RubyGems

gems TMail which allows us to manipulate email objects conveniently, and mime-types which guesses a file's mime type based on its filename.

<lang ruby>require 'base64' require 'net/smtp' require 'tmail' require 'mime/types'

class Email

 def initialize(from, to, subject, body, options={})
   @opts = {:attachments => [], :server => 'localhost'}.update(options)
   @msg = TMail::Mail.new
   @msg.from    = from
   @msg.to      = to
   @msg.subject = subject
   @msg.cc      = @opts[:cc]  if @opts[:cc]
   @msg.bcc     = @opts[:bcc] if @opts[:bcc]
   if @opts[:attachments].empty?
     # just specify the body
     @msg.body = body
   else
     # attach attachments, including the body
     @msg.body = "This is a multi-part message in MIME format.\n"
     msg_body = TMail::Mail.new
     msg_body.body = body
     msg_body.set_content_type("text","plain", {:charset => "ISO-8859-1"})
     @msg.parts << msg_body
     octet_stream = MIME::Types['application/octet-stream'].first
     @opts[:attachments].select {|file| File.readable?(file)}.each do |file|
       mime_type = MIME::Types.type_for(file).first || octet_stream
       @msg.parts << create_attachment(file, mime_type)
     end
   end
 end
 attr_reader :msg
 def create_attachment(file, mime_type)
   attach = TMail::Mail.new
   if mime_type.binary?
     attach.body = Base64.encode64(File.read(file))
     attach.transfer_encoding = 'base64'
   else
     attach.body = File.read(file)
   end
   attach.set_disposition("attachment", {:filename => file})
   attach.set_content_type(mime_type.media_type, mime_type.sub_type, {:name=>file})
   attach
 end
 # instance method to send an Email object
 def send
   args = @opts.values_at(:server, :port, :helo, :username, :password, :authtype)
   Net::SMTP.start(*args) do |smtp|
     smtp.send_message(@msg.to_s, @msg.from[0], @msg.to)
   end
 end
 # class method to construct an Email object and send it
 def self.send(*args)
   self.new(*args).send
 end

end

Email.send(

 'sender@sender.invalid',
 %w{ recip1@recipient.invalid recip2@example.com },
 'the subject',
 "the body\nhas lines",
 {
   :attachments => %w{ file1 file2 file3 },
   :server => 'mail.example.com',
   :helo => 'sender.invalid',
   :username => 'user',
   :password => 'secret'
 }

)</lang>

Tcl

Library: Tcllib (Package: mime)
Library: Tcllib (Package: smtp)

Also may use the tls package (needed for sending via gmail). <lang tcl>package require smtp package require mime package require tls

set gmailUser ******* set gmailPass hunter2; # Hello, bash.org!

proc send_simple_message {recipient subject body} {

   global gmailUser gmailPass
   # Build the message
   set token [mime::initialize -canonical text/plain -string $body]
   mime::setheader $token Subject $subject
   # Send it!
   smtp::sendmessage $token -userame $gamilUser -password $gmailPass \
           -recipients $recipient -servers smtp.gmail.com -ports 587
   # Clean up
   mime::finalize $token

}

send_simple_message recipient@example.com "Testing" "This is a test message."</lang>

TUSCRIPT

works only with Windows, on Linux OS it is possible to send an email by using the Execute function <lang tuscript> $$ MODE TUSCRIPT

system=SYSTEM ()

IF (system=="WIN") THEN SET to="name@domain.org" SET cc="name@domain.net" subject="test" text=* DATA how are you?

status = SEND_MAIL (to,cc,subject,text,-)

ENDIF </lang>