Phantom Kirby Theme - Contact Form Not Working

I have download the Kirby Phantom Theme and installed whit the Kirby Version 2.2.3, the theme is included whit a nice little contact form

if i enter some text and a valid email adresse i got this error


Warning: mail(): Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in C:\xampp\htdocs\portfolio-app2\kirby\toolkit\lib\email.php on line 159

Fatal error: Uncaught Error: The email could not be sent in C:\xampp\htdocs\portfolio-app2\kirby\toolkit\lib\email.php:163 Stack trace: #0 C:\xampp\htdocs\portfolio-app2\kirby\toolkit\helpers.php(270): {closure}(Object(Email)) #1 C:\xampp\htdocs\portfolio-app2\kirby\toolkit\lib\email.php(127): call(Object(Closure), Array) #2 C:\xampp\htdocs\portfolio-app2\site\controllers\home.php(21): Email->send() #3 C:\xampp\htdocs\portfolio-app2\kirby\kirby.php(525): Kirby->{closure}(Object(Site), Object(Children), Object(Page), Array) #4 C:\xampp\htdocs\portfolio-app2\kirby\kirby.php(699): Kirby->controller(Object(Page), Array) #5 C:\xampp\htdocs\portfolio-app2\kirby\kirby.php(680): Kirby->template(Object(Page), Array) #6 C:\xampp\htdocs\portfolio-app2\kirby\kirby.php(781): Kirby->render(Object(Page)) #7 C:\xampp\htdocs\portfolio-app2\index.php(16): Kirby->launch() #8 {main} thrown in C:\xampp\htdocs\portfolio-app2\kirby\toolkit\lib\email.php on line 163
<?php

/**
 * Email
 *
 * A simple email handling class which supports
 * multiple email services. Check out the email subfolder
 * for all available services
 *
 * @package   Kirby Toolkit
 * @author    Bastian Allgeier <bastian@getkirby.com>
 * @link      http://getkirby.com
 * @copyright Bastian Allgeier
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 */
class Email extends Obj {

  const ERROR_INVALID_RECIPIENT = 0;
  const ERROR_INVALID_SENDER = 1;
  const ERROR_INVALID_REPLY_TO = 2;
  const ERROR_INVALID_SUBJECT = 3;
  const ERROR_INVALID_BODY = 4;
  const ERROR_INVALID_SERVICE = 5;
  const ERROR_DISABLED = 6;

  public static $defaults = array(
    'service' => 'mail',
    'options' => array(),
    'to'      => null,
    'from'    => null,
    'replyTo' => null,
    'subject' => null,
    'body'    => null
  );

  public static $services = array();
  public static $disabled = false;

  public $error;
  public $service;
  public $options;
  public $to;
  public $from;
  public $replyTo;
  public $subject;
  public $body;

  public function __construct($params = array()) {
    $options = a::merge(static::$defaults, $params);
    parent::__construct($options);
  }

  public function __set($key, $value) {
    $this->$key = $value;
  }

  /**
   * Validates the constructed email
   * to make sure it can be sent at all
   */
  public function validate() {
    if(!v::email($this->extractAddress($this->to)))      throw new Error('Invalid recipient', static::ERROR_INVALID_RECIPIENT);
    if(!v::email($this->extractAddress($this->from)))    throw new Error('Invalid sender', static::ERROR_INVALID_SENDER);
    if(!v::email($this->extractAddress($this->replyTo))) throw new Error('Invalid reply address', static::ERROR_INVALID_REPLY_TO);
    if(empty($this->subject))    throw new Error('Missing subject', static::ERROR_INVALID_SUBJECT);
    if(empty($this->body))       throw new Error('Missing body', static::ERROR_INVALID_BODY);
  }

  /**
   * Public getter for the error exception
   *
   * @return Exception
   */
  public function error() {
    return $this->error;
  }

  /**
   * Extracts the email address from an address string
   *
   * @return string
   */
  protected function extractAddress($string) {
    if(v::email($string)) return $string;
    preg_match('/<(.*?)>/i', $string, $array);
    return (empty($array[1])) ? $string : $array[1];
  }

  /**
   * Sends the constructed email
   *
   * @param array $params Optional way to set values for the email
   * @return boolean
   */
  public function send($params = null) {

    try {

      // fail silently if sending emails is disabled
      if(static::$disabled) throw new Error('Sending emails is disabled', static::ERROR_DISABLED);

      // overwrite already set values
      if(is_array($params) && !empty($params)) {
        foreach(a::merge($this->toArray(), $params) as $key => $val) {
          $this->set($key, $val);
        }
      }

      // reset all errors  
      $this->error = null;

      // default service
      if(empty($this->service)) $this->service = 'mail';

      // if there's no dedicated reply to address, use the from address
      if(empty($this->replyTo)) $this->replyTo = $this->from;

      // validate the email
      $this->validate();

      // check if the email service is available
      if(!isset(static::$services[$this->service])) {
        throw new Error('The email service is not available: ' . $this->service, static::ERROR_INVALID_SERVICE);
      }

      // run the service
      call(static::$services[$this->service], $this);

      // reset the error
      $this->error = null;
      return true;

    } catch(Exception $e) {
      $this->error = $e;
      return false;
    }

  }

}


/**
 * Default mail driver
 */
email::$services['mail'] = function($email) {

  $headers = array(
    'From: ' . $email->from,
    'Reply-To: ' . $email->replyTo,
    'Return-Path: ' . $email->replyTo,
    'Message-ID: <' . time() . '-' . $email->from . '>',
    'X-Mailer: PHP v' . phpversion(),
    'Content-Type: text/plain; charset=utf-8',
    'Content-Transfer-Encoding: 8bit',
  );

  ini_set('sendmail_from', $email->from);
  $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers));
  ini_restore('sendmail_from');

  if(!$send) {
    throw new Error('The email could not be sent');
  }

};

/**
 * Amazon mail driver
 */
email::$services['amazon'] = function($email) {

  if(empty($email->options['key']))    throw new Error('Missing Amazon API key');
  if(empty($email->options['secret'])) throw new Error('Missing Amazon API secret');

  $setup = array(
    'Action'                           => 'SendEmail',
    'Destination.ToAddresses.member.1' => $email->to,
    'ReplyToAddresses.member.1'        => $email->replyTo,
    'ReturnPath'                       => $email->replyTo,
    'Source'                           => $email->from,
    'Message.Subject.Data'             => $email->subject,
    'Message.Body.Text.Data'           => $email->body
  );

  $params = array();

  foreach($setup as $key => $value) {
    $params[] = $key . '=' . str_replace('%7E', '~', rawurlencode($value));
  }

  sort($params, SORT_STRING);

  $host      = a::get($email->options, 'host', 'email.us-east-1.amazonaws.com');
  $url       = 'https://' . $host . '/';
  $date      = gmdate('D, d M Y H:i:s e');
  $signature = base64_encode(hash_hmac('sha256', $date, $email->options['secret'], true));
  $query     = implode('&', $params);
  $headers   = array();
  $auth      = 'AWS3-HTTPS AWSAccessKeyId=' . $email->options['key'];
  $auth     .= ',Algorithm=HmacSHA256,Signature=' . $signature;

  $headers[] = 'Date: ' . $date;
  $headers[] = 'Host: ' . $host;
  $headers[] = 'X-Amzn-Authorization: '. $auth;
  $headers[] = 'Content-Type: application/x-www-form-urlencoded';

  $email->response = remote::post($url, array(
    'data'    => $query,
    'headers' => $headers
  ));

  if(!in_array($email->response->code(), array(200, 201, 202, 204))) {
    throw new Error('The mail could not be sent!', $email->response->code());
  }

};

/**
 * Mailgun mail driver
 */
email::$services['mailgun'] = function($email) {

  if(empty($email->options['key']))    throw new Error('Missing Mailgun API key');
  if(empty($email->options['domain'])) throw new Error('Missing Mailgun API domain');

  $url  = 'https://api.mailgun.net/v2/' . $email->options['domain'] . '/messages';
  $auth = base64_encode('api:' . $email->options['key']);

  $headers = array(
    'Accept: application/json',
    'Authorization: Basic ' . $auth
  );

  $data = array(
    'from'       => $email->from,
    'to'         => $email->to,
    'subject'    => $email->subject,
    'text'       => $email->body,
    'h:Reply-To' => $email->replyTo,
  );

  $email->response = remote::post($url, array(
    'data'    => $data,
    'headers' => $headers
  ));

  if($email->response->code() != 200) {
    throw new Error('The mail could not be sent!');
  }

};

/**
 * Postmark mail driver
 */
email::$services['postmark'] = function($email) {

  if(empty($email->options['key'])) throw new Error('Invalid Postmark API Key');

  // reset the api key if we are in test mode
  if(a::get($email->options, 'test')) $email->options['key'] = 'POSTMARK_API_TEST';

  // the url for postmarks api
  $url = 'https://api.postmarkapp.com/email';

  $headers = array(
    'Accept: application/json',
    'Content-Type: application/json',
    'X-Postmark-Server-Token: ' . $email->options['key']
  );

  $data = array(
    'From'     => $email->from,
    'To'       => $email->to,
    'ReplyTo'  => $email->replyTo,
    'Subject'  => $email->subject,
    'TextBody' => $email->body
  );

  // fetch the response
  $email->response = remote::post($url, array(
    'data'    => json_encode($data),
    'headers' => $headers
  ));

  if($email->response->code() != 200) {
    throw new Error('The mail could not be sent');
  }

};


?>

Hope you can help me :blush:

Have a Nice Day :smiley:

Simon

That’s not a problem of the theme but of your settings. Usually, sending mails is disabled on localhost and you would have to set it up first.

i have changed the email in the Settings to my Email Adresse

You need to setup an email client on your local host installation (wamp or xamp or whatever you’re using) which is usually a hassle. Can you try to test this on a development environment that is not locally hosted?

This might help: http://stackoverflow.com/questions/15965376/how-to-configure-xampp-to-send-mail-from-localhost

i already have it :slight_smile: thanks @texnixe and @Thiousi

What was your solution? I am scratching ym head with this. I have setup sendmail and edited the php.ini as well as the sendmail.ini but it just goes straight to;

Fatal error: Uncaught Error: The email could not be sent in C:\wamp64\www\pearshaped\kirby\toolkit\lib\email.php on line 163
[22-May-2016 08:38:19 UTC] PHP Fatal error:  Uncaught Error: The email could not be sent in C:\wamp64\www\pearshaped\kirby\toolkit\lib\email.php:163
Stack trace:
#0 C:\wamp64\www\pearshaped\kirby\toolkit\helpers.php(270): {closure}(Object(Email))
#1 C:\wamp64\www\pearshaped\kirby\toolkit\lib\email.php(127): call(Object(Closure), Array)
#2 C:\wamp64\www\pearshaped\site\controllers\home.php(21): Email->send()
#3 C:\wamp64\www\pearshaped\kirby\core\page.php(1415): Kirby\Registry\Controller->{closure}(Object(Site), Object(Children), Object(Page), Array)
#4 C:\wamp64\www\pearshaped\kirby\kirby\component\template.php(33): PageAbstract->controller(Array)
#5 C:\wamp64\www\pearshaped\kirby\kirby\component\template.php(70): Kirby\Component\Template->data(Object(Page), Array)
#6 C:\wamp64\www\pearshaped\kirby\kirby.php(619): Kirby\Component\Template->render(Object(Page), Array)
#7 C:\wamp64\www\pearshaped\kirby\kirby.php(607): Kirby->template(Object(Page), Array)
#8 C:\wamp64\www\pearshaped\kirby\kirby\component\response.php(29): Kirby->render(Object(Page))
#9 C:\ in C:\wamp64\www\pearshaped\kirby\toolkit\lib\email.php on line 163

Instead of opening a new thread i thought i would ask here Any ideas?

Thanks,
T+

i hope this help’s you: http://stackoverflow.com/questions/5773288/configure-wamp-server-to-send-email

EDIT: i have found a tutorial on youtube, maybe its helpfull

The email class uses the built-in PHP mail() function. It is unfortunately very hard to debug as it just returns false on error. Are there any other warnings or errors on the page or in your PHP error log?

Thanks @lukasbestle and @thesmithy :slight_smile:

It turns out it was a combination of using PHP7, Wamp and generally not knowing what the heck I was doing.
I started from scratch and installed Xampp configured the php.ini like so;

SMTP=smtp.gmail.com
smtp_port=587
sendmail_from = youraccount@gmail.com
sendmail_path = "\"C:\xampp\sendmail\sendmail.exe\" -t"

Sendmail.ini

smtp_server=smtp.gmail.com
smtp_port=587
error_logfile=error.log
debug_logfile=debug.log
auth_username=youraccount@gmail.com
auth_password=pass
force_sender=youraccount@gmail.com

You must quit xampp and stop & restart the services in the windows mgmt console (or just reboot).

Works fine now apart from the issue it gives a “1” on successful submission of form. Looking into that.

1 Like

hi @typeplus,
You should use three backticks instead of one to display code blocks
with one backtick

    with three backticks
    you're better off
1 Like