Search code examples
phpcodeigniter

Why does adding extra headers to this Codeigniter 3 form make it fail?


I am working on an online newspaper/blogging application with CodeIgniter 3.1.8 and Twig.

I have added a contact form to the application:

{% if errors %}
    <div class="alert-box alert-box--error">{{errors | raw}}</div>
{% endif %}

<form name="contactForm" id="ajaxForm" class="s-content__form"
    action="{{base_url}}contact"
        method="post"
            data-successmsg="Your message was sent. We will reply as soon as possible." 
                data-failmsg="Sorry, we could not deliver your message"
                    novalidate>
                    <fieldset>      
                        <div class="form-field">
                                <input type="text" class="h-full-width" placeholder="Name" name="name" id="name" data-rule-required="true" value="{{set_value('name') | striptags}}">
                        </div>
                        <div class="form-field">
                                <input type="email" class="h-full-width" placeholder="Email" name="email" id="email" data-rule-required="true" value="{{set_value('email') | striptags}}">
                            </div>
                        <div class="form-field">
                                <input type="text" class="h-full-width" placeholder="Subject" name="subject" id="subject"  data-rule-required="true" value="{{set_value('subject') | striptags}}">
                        </div>
                        <div class="form-field">
                                <textarea rows="5" class="h-full-width" placeholder="Message" name="message" id="message" data-rule-required="true">{{set_value('message') | striptags}}</textarea>
                        </div>
                        <button type="submit" class="submit btn btn--primary h-full-width" id="sendMessageButton">Send</button>
                    </fieldset>
</form>

{% if message_success == true %}
    <div class="alert-box alert-box--success text-center">
        <span class="alert-box__close"></span>
        Your message was sent. We will reply as soon as possible.
    </div>
{% endif %}

{% if message_fail == true %}
    <div class="alert-box alert-box--error">
        <span class="alert-box__close"></span>
        Sorry, we could not deliver your message
    </div>
{% endif %}

<div id="msgContainer" class="is-hidden alert-box alert-box--{{ message_success ? 'success' : 'error' }} text-center"></div>

The form works unless I add (extra) headers to it.

Here is the controller:

class Contact extends CI_Controller {

    public function __construct() {
        parent::__construct();
    }

    private $headers = '';
    private $from = '[email protected]';
    private $to = '[email protected]'; 
    private $email_address = '';
    private $name = '';
    private $subject = ''; 
    private $message = '';
    private $body = '';

    private $message_success = false;
    private $message_fail = false;

    public function index(){    
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('email', 'Email', 'required|trim|valid_email');
        $this->form_validation->set_rules('subject', 'Subject', 'required');
        $this->form_validation->set_rules('message', 'Message', 'required');
        $this->form_validation->set_error_delimiters('<p class="form-error">', '</p>');

        $this->displayForm();

        if($this->form_validation->run() === FALSE) {
            $data['errors'] = validation_errors();
        } else {
            //Prepare mail
            $this->subject = "Website Contact Form: " . $this->input->post('subject');
            $this->name = $this->input->post('name');
            $this->email_address = $this->input->post('email');
            $this->message = $this->input->post('message');
            $this->body = "You have received a new message from your website contact form. Here are the details:\n\nName: $this->name\n\nEmail: $this->email_address\n\nMessage:\n$this->message";
            $this->headers = "From: . $this->from\n";
            $this->headers .= "Reply-To: $this->email_address"; 

            //Send mail
            $this->send_mail();
        }       
    }

    public function displayForm() {

    $data = $this->Static_model->get_static_data();
        $data['base_url'] = base_url("/");
        $data['pages'] = $this->Pages_model->get_pages();
        $data['categories'] = $this->Categories_model->get_categories();
        $data['tagline'] = "Contact us";
        $data['errors'] = validation_errors();
        $data['message_success'] = $this->message_success;
        $data['message_fail'] = $this->message_fail;

        $this->twig->addGlobal('contactForm',"themes/{$data['theme_directory']}/templates/contact.twig");
        $this->twig->display("themes/{$data['theme_directory']}/layout", $data);
    }
    
    //mail sender method
    public function send_mail() {
            $config['protocol'] = 'sendmail';
            $config['charset'] = 'utf-8';
            $config['mailtype'] = 'html';

        
        if(!$this->load->is_loaded('email')){
                $this->load->library('email', $config);
            } else {
                $this->email->initialize($config);
            }

    $this->email->from($this->from);
    $this->email->to($this->to);
    //this line makes it fail
    $this->email->set_header($this->headers);
    $this->email->subject($this->subject);
    $this->email->message($this->body);

        if ($this->email->send()) {
            $this->message_success = true;
        } else {
            $this->message_fail = true;
        }
    }
    
}

If I remove $this->email->set_header($this->headers) from the above code, the email is sent successfully. But I would rather keep it.

How do I keep the headers and make it work?


Solution

  • You need to put headers separately into an array and add these by a loop to the Email library:

    private $headers = array();
    public function index(){
        ...
        $this->headers["From"] = " $this->from\n";
        $this->headers["Reply-To"] = ": $this->email_address";
    ...
    }
    
    // In send_mail function:
    ...
    foreach($this->headers as $key => $value){
        $this->email->set_header($key, $value);
    }
    ...