I'm trying to send an email from a contact form that is on my page, I'm using a PHP script to send it to my email, I'm following this tutorial, I've used his example and it does work... but I can't seem to get it to work in my application, I was having some trouble at first with 404
errors but I then published my site and put it on a live server and now I'm getting success codes
but im not getting the emails, so I went to http://mysite/assets/email.php and Im seeing this error
get-in-touchponent.ts
import { Component, OnInit } from '@angular/core';
import { AppService, IMessage } from '../../services/email.service';
@Component({
selector: 'app-get-in-touch',
templateUrl: './get-in-touchponent.html',
styleUrls: ['./get-in-touchponent.scss'],
providers: [AppService]
})
export class GetInTouchComponent implements OnInit {
message: IMessage = {};
constructor(
private appService: AppService
) { }
ngOnInit() {
}
sendEmail(message: IMessage) {
this.appService.sendEmail(message).subscribe(res => {
console.log('AppComponent Success', res);
}, error => {
console.log('AppComponent Error', error);
});
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes, ActivatedRoute, ParamMap } from '@angular/router';
import { AppComponent } from './appponent';
import { GetInTouchComponent } from './get-in-touch/get-in-touchponent';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { httpModule } from @angular/forms;
export const ROUTES: Routes = [
{ path: 'get-in-touch', ponent: GetInTouchComponent }
];
@NgModule({
declarations: [
AppComponent,
GetInTouchComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES),
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
email.service.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Resolve } from '@angular/router';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
export interface IMessage {
name?: string;
email?: string;
message?: string;
}
@Injectable()
export class AppService {
private emailUrl = '../app/get-in-touch/email.php';
constructor(private http: Http) {
}
sendEmail(message: IMessage): Observable<IMessage> | any {
return this.http.post(this.emailUrl, message)
.map(response => {
console.log('Sending email was successfull', response);
return response;
})
.catch(error => {
console.log('Sending email got error', error);
return Observable.throw(error);
});
}
}
email.php
<?php
header('Content-type: application/json');
$errors = '';
if(empty($errors)){
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$from_email = $request->email;
$message = $request->message;
$from_name = $request->name;
$to_email = $from_email;
$contact = "<p><strong>Name: </strong> $from_name</p><p><strong>Email:</strong> $from_email</p>";
$content = "<p>$message</p>";
$website = "Thirsty Studios";
$email_subject = "Contact Form";
$email_body = '<html><body>';
$email_body .= '$contact $content';
$email_body .= '</body></html>';
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$headers .= "From: $from_email\n";
$headers .= "Reply-To: $from_email";
mail($to_email,$email_subject,$email_body,$headers);
$response_array['status'] = 'success';
$response_array['from'] = $from_email;
echo json_encode($response_array);
echo json_encode($from_email);
header($response_array);
return $from_email;
} else {
$response_array['status'] = 'error';
echo json_encode($response_array);
header('Location: /error.html');
}
?>
I've never done anything like this before (Angular + PHP), but I have done everything that is said in the tutorial and I can't seem to get it to work, any help would be appreciated and please let me know if you need more information
I'm trying to send an email from a contact form that is on my page, I'm using a PHP script to send it to my email, I'm following this tutorial, I've used his example and it does work... but I can't seem to get it to work in my application, I was having some trouble at first with 404
errors but I then published my site and put it on a live server and now I'm getting success codes
but im not getting the emails, so I went to http://mysite/assets/email.php and Im seeing this error
get-in-touch.ponent.ts
import { Component, OnInit } from '@angular/core';
import { AppService, IMessage } from '../../services/email.service';
@Component({
selector: 'app-get-in-touch',
templateUrl: './get-in-touch.ponent.html',
styleUrls: ['./get-in-touch.ponent.scss'],
providers: [AppService]
})
export class GetInTouchComponent implements OnInit {
message: IMessage = {};
constructor(
private appService: AppService
) { }
ngOnInit() {
}
sendEmail(message: IMessage) {
this.appService.sendEmail(message).subscribe(res => {
console.log('AppComponent Success', res);
}, error => {
console.log('AppComponent Error', error);
});
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes, ActivatedRoute, ParamMap } from '@angular/router';
import { AppComponent } from './app.ponent';
import { GetInTouchComponent } from './get-in-touch/get-in-touch.ponent';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { httpModule } from @angular/forms;
export const ROUTES: Routes = [
{ path: 'get-in-touch', ponent: GetInTouchComponent }
];
@NgModule({
declarations: [
AppComponent,
GetInTouchComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES),
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
email.service.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Resolve } from '@angular/router';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
export interface IMessage {
name?: string;
email?: string;
message?: string;
}
@Injectable()
export class AppService {
private emailUrl = '../app/get-in-touch/email.php';
constructor(private http: Http) {
}
sendEmail(message: IMessage): Observable<IMessage> | any {
return this.http.post(this.emailUrl, message)
.map(response => {
console.log('Sending email was successfull', response);
return response;
})
.catch(error => {
console.log('Sending email got error', error);
return Observable.throw(error);
});
}
}
email.php
<?php
header('Content-type: application/json');
$errors = '';
if(empty($errors)){
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$from_email = $request->email;
$message = $request->message;
$from_name = $request->name;
$to_email = $from_email;
$contact = "<p><strong>Name: </strong> $from_name</p><p><strong>Email:</strong> $from_email</p>";
$content = "<p>$message</p>";
$website = "Thirsty Studios";
$email_subject = "Contact Form";
$email_body = '<html><body>';
$email_body .= '$contact $content';
$email_body .= '</body></html>';
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$headers .= "From: $from_email\n";
$headers .= "Reply-To: $from_email";
mail($to_email,$email_subject,$email_body,$headers);
$response_array['status'] = 'success';
$response_array['from'] = $from_email;
echo json_encode($response_array);
echo json_encode($from_email);
header($response_array);
return $from_email;
} else {
$response_array['status'] = 'error';
echo json_encode($response_array);
header('Location: /error.html');
}
?>
I've never done anything like this before (Angular + PHP), but I have done everything that is said in the tutorial and I can't seem to get it to work, any help would be appreciated and please let me know if you need more information
Share Improve this question edited Dec 18, 2017 at 10:49 giannis christofakis 8,3124 gold badges55 silver badges66 bronze badges asked Dec 15, 2017 at 0:31 Smokey DawsonSmokey Dawson 9,24023 gold badges85 silver badges162 bronze badges 6- Can you check if you can actually access this URL localhost:4200/app/get-in-touch/email.php in your browser, since you are having 404 error. – Kamal Soni Commented Dec 15, 2017 at 5:51
- Hey yes, I tried to access that URL and it didn't work so what I did was moved email.php into my assets folder and I was able to access it.. but I'm still getting the same error I'm wondering if it's not working because I am on localhost? – Smokey Dawson Commented Dec 15, 2017 at 11:16
- What is the full URL of the page where the form is displayed? – Kamal Soni Commented Dec 16, 2017 at 5:09
- its running locally so localhost:4200/get-in-touch – Smokey Dawson Commented Dec 17, 2017 at 6:14
- Are you still getting exactly the same first error, even after you fixed the email.php URL? If not can you please update your first error image. Thanks – Kamal Soni Commented Dec 17, 2017 at 6:51
2 Answers
Reset to default 3 +50At this point it seems as though the request does not even reach your PHP script as the request returns a 404. The first error likely occurs because the node server will not execute .php
files. You will need to set up a local Apache server on a different port using something like xammp (or your preferred alternative). Or otherwise make your request to a live web server.
It seems like the second and third error messages could be ing form your .catch
callback in your email service, try using the following:
.catch((error: Error) => {
console.log('Sending email got error', error.message);
return Observable.throw(error.message);
});
There are some alternatives to using PHP, such as formspree or even the Gmail API and I'm sure you will find others with a bit of Googling. But here is an example using fromspree.
You should also be able to simplify you PHP script slightly as follows:
<?php
$errors = '';
if( empty( $errors ) ) {
$response_array = array();
$from_email = $_POST['email'];
$message = $_POST['message'];
$from_name = $_POST['name'];
$to_email = $from_email;
$contact = "<p><strong>Name: </strong> $from_name</p><p><strong>Email:</strong> $from_email</p>";
$content = "<p>$message</p>";
$website = "Thirsty Studios";
$email_subject = "Contact Form";
$email_body = "<html><body>";
$email_body .= "$contact $content";
$email_body .= "</body></html>";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$headers .= "From: $from_email\n";
$headers .= "Reply-To: $from_email";
mail( $to_email, $email_subject, $email_body, $headers );
$response_array['status'] = 'success';
$response_array['from'] = $from_email;
echo json_encode( $response_array );
} else {
$response_array['status'] = 'error';
echo json_encode($response_array);
}
?>
I'm not 100% convinced that I can give you an exact answer, but I think there are some overall issues/confusions/misunderstandings that you are running into, and understanding them may help get you moving in the right direction.
First of all, you should ignore the angular for now and only consider the PHP (which you have tried to do). Angular is basically a red-herring: if your can get your PHP script to send emails without using Angular, then it will be easy to get Angular to send emails using the PHP endpoint. The trick is that your script currently accepts its input via the POST body with JSON, so if you were to simply load it up in your browser, nothing will happen. Instead you can test this endpoint directly with things like curl. If you have curl installed you can do something like this from the mand line:
curl -d '{"email":"[email protected]", "message": "Hi", "name": "Conor Mancone"}' 'http://example./email.php'
The d
flag specifies the post data (and implicitly flags for a POST request). If you don't have curl installed locally you can use online curl or install postman. These are tools that you might as well start learning now.
This will let you debug your PHP endpoint much more effectively. Most importantly, you will be able to see the output directly. Next step is to copy and paste the output into something like jsonlint. It looks like your PHP endpoint is not properly returning JSON, and this will let you figure that part out. Most importantly though, you can ignore angular and figure out why you aren't sending emails. On that note, let's jump into the PHP and talk about some of the general issues in your code, which may or may not be causing your problems, but certainly aren't helping your cause:
$errors = '';
if(empty($errors)){
// send email
} else {
// return error
}
This first part is fairly obvious to someone who looks at your code for the first time. You make $errors
empty and then all of your email-sending logic is wrapped in a if (empty($errors))
condition. Lose the $errors
variable. Lose that if-else. Never leave code in your application that doesn't actually do anything. It just gives you more opportunities to introduce bugs for no reason.
Also, this is a minor point, but you aren't doing any input validation. If the JSON posted to your endpoint is missing some data your script will crash. Someone could put HTML in the message which can be obnoxious at best or dangerous at worst.
You've also got a bunch of bugs at the end of your script:
echo json_encode($response_array);
echo json_encode($from_email);
header($response_array);
return $from_email;
You are outputting $response_array
as JSON to the browser, then you are running json_encode
on a string ($from_email
) which won't even form valid JSON, and the bination of both of them definitely won't be valid JSON. You should have only one echo json_encode
, otherwise the result will not be valid JSON, and you'll get a parse error in your angular front-end.
Next up, you are passing your $response_array
to the php header
function. This is definitely not doing anything for you. header
is expecting a string, not an array, and is used to set HTTP header key/value pairs in the HTTP response. I can't imagine you want to set any of the data in your $response_array
as HTTP header response values, and even if you did want to do that, you can't do it by passing in the $response_array
itself. Therefore, definitely kill this line. PHP is silently ignoring it anyway.
Similarly, there is no reason to return anything. A return from the file being executed by the HTTP request will have no impact at all. Generally, you shouldn't be returning outside of functions (and this isn't a function). While I don't believe this line is causing any errors, it also isn't doing anything. If it isn't doing anything then remove it. To be clear, I'm talking about this line: return $from_email;
.
All this script should be doing is reading in the post data, sending an email, and then echoing out a single call to json_encode
. Anything more than that will end up with invalid JSON which your front-end app won't be able to read. Again, use curl
(or other similar tools) to call your PHP script directly and debug it more easily. This way you can see what it is outputting and verify that it is returning proper JSON.
Now then, onto the main issue: lack of email sending. You've definitely got some malformed mail headers. Every mail header needs to end in \r\n
. You start off good, but your last two header lines don't end properly. This might be enough to sink your email sending attempts. PHP's built in mail
function doesn't do a great job of notifying you of errors, so you might actually be better off using a more robust mailer. This will give you better feedback if you make mistakes while configuring your email. A mon one in PHP is this guy:
https://github./PHPMailer/PHPMailer
I would start by fixing your email headers and see if that does it for you. Otherwise though, you may have to try out an actual mailer. The reason is because the next most mon reason why email-sending doesn't work is because of modern efforts of spam mitigation. The PHP mail
function is going to send off an email directly from the server itself. Many modern email systems (especially gmail) will automatically reject such emails unless the domain name you are sending from is properly configured at the DNS level. However, you are sending from arbitrary email addresses (the contents of the $from_email
variable, which es from the user). Many email providers these days will automatically reject such emails, and PHP will have no idea that happened and won't give you any indication of it.
Instead, send from a fixed address that you control. Either pass along the $from_email
in the email message, or set it as the reply-to. Your very best bet is to use an actual email address and authenticate using SMTP. Gmail actually works fine for this. You should be able to find some examples of how to use the above PHPMailer with gmail to send directly from your gmail address. This will minimize the chances of your emails being rejected as spam, and also give you additional feedback (if it is in your sent box, but didn't show up, then it was rejected as spam).
Sending emails is tricky these days. It's not as simple as calling the mail
function.