电子邮件无法发送 Angular 4 & PHP

5

我正在尝试从我的页面上的联系表单发送电子邮件,我正在使用PHP脚本将其发送到我的电子邮件中,我正在遵循this教程,我已经使用了他的示例,并且它确实有效...但是我似乎无法让它在我的应用程序中工作,一开始我遇到了一些404错误,但我随后发布了我的网站并将其放在一个实时服务器上,现在我收到了成功代码

enter image description here

但我没有收到电子邮件,所以我访问了http://mysite/assets/email.php,并看到了这个错误。

enter image description here

get-in-touch.component.ts

import { Component, OnInit } from '@angular/core';
import { AppService, IMessage } from '../../services/email.service';

@Component({
  selector: 'app-get-in-touch',
  templateUrl: './get-in-touch.component.html',
  styleUrls: ['./get-in-touch.component.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.component';
import { GetInTouchComponent } from './get-in-touch/get-in-touch.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { httpModule } from @angular/forms;

export const ROUTES: Routes = [
  { path: 'get-in-touch', component: 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');
}
?>

我以前从未做过这样的事情(Angular + PHP),但我已经按照教程中所说的做了一切,但似乎无法使其正常工作,如果需要更多信息,请告诉我,任何帮助将不胜感激。


你能否在浏览器中检查一下,是否可以访问这个URL http://localhost:4200/app/get-in-touch/email.php?因为你遇到了404错误。 - Kamal Soni
嘿,是的,我尝试访问那个URL,但它没有工作,所以我把email.php移动到我的资产文件夹中,然后我能够访问它..但我仍然得到相同的错误,我想知道是否因为我在本地主机上而无法工作? - Smokey Dawson
表单显示的完整页面URL是什么? - Kamal Soni
它正在本地运行,因此本地主机为localhost:4200/get-in-touch。 - Smokey Dawson
你在修复了email.php的URL之后,是否仍然遇到完全相同的第一个错误?如果不是,请更新您的第一个错误图像。谢谢。 - Kamal Soni
是的,仍然是相同的错误信息。我会更新照片。 - Smokey Dawson
2个回答

3
在这个阶段,似乎请求甚至没有到达您的PHP脚本,因为该请求返回404错误。第一个错误可能是因为节点服务器不会执行.php文件。您需要使用类似xammp(或您喜欢的替代品)设置本地Apache服务器以不同的端口运行。或者将请求发送到实时Web服务器。
似乎第二个和第三个错误消息可能来自于您电子邮件服务的.catch回调函数,请尝试使用以下内容:
.catch((error: Error) => {
  console.log('Sending email got error', error.message);
  return Observable.throw(error.message);
});

有一些替代PHP的选择,比如formspree或者甚至是Gmail API,我相信你可以通过谷歌找到其他选项。但是这里提供一个使用formspree的例子

你应该能够按照以下方式稍微简化你的PHP脚本:

<?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);
}
?>

所以我发布了我的项目并将其放在实时开发服务器上,我收到了成功消息(请参见更新的问题),但实际上我并没有收到电子邮件。 - Smokey Dawson
好的,我认为你可以稍微简化一下你的邮件脚本,看看更新后的答案。 - Michael Doye
@A61NN5 你有检查过垃圾邮件文件夹吗?当你浏览电子邮件脚本时,你是否收到了电子邮件?首先测试一下这个,然后你就应该能理解这个错误了。另外从你的代码来看,这需要放在双引号内,否则它只会打印变量´$email_body .= '$contact $content';´ - Manzurul
嘿,谢谢。经过大量的调试,我决定使用formspree,它更简单,而且它可以正常工作。感谢您的建议! - Smokey Dawson

3
我无法百分之百肯定我能给你一个确切的答案,但我认为你遇到了一些整体性的问题/混淆/误解,理解它们可能有助于使你朝着正确的方向前进。首先,你应该暂时忽略Angular,只考虑PHP(这是你已经尝试过的)。Angular基本上是一个红鲱鱼:如果你能让你的PHP脚本在不使用Angular的情况下发送电子邮件,那么使用PHP端点发送电子邮件将变得很容易。诀窍在于你的脚本当前通过JSON的POST方式接收其输入,因此如果你简单地在浏览器中加载它,什么都不会发生。相反,你可以使用curl等工具直接测试这个端点。如果你已经安装了curl,你可以在命令行中执行以下操作:
curl -d '{"email":"johndoe@example.com", "message": "Hi", "name": "Conor Mancone"}' 'http://example.com/email.php'
d标志指定了提交的数据(并隐含地标记为POST请求)。如果您没有在本地安装curl,可以使用在线curl或安装postman。这些工具你最好现在就开始学习。
这将让您更有效地调试PHP端点。最重要的是,您将能够直接查看输出。下一步是将输出复制并粘贴到类似jsonlint的工具中。看起来您的PHP端点没有正确返回JSON,这将帮助您找出问题所在。最重要的是,您可以忽略angular并找出为什么您无法发送电子邮件。在此提醒一下,让我们进入PHP并谈论一些代码中的一般性问题,这些问题可能会导致问题,但肯定不会有所帮助:
$errors = '';

if(empty($errors)){
    // send email
} else {
    // return error
}

这部分对于第一次查看您的代码的人来说是相当明显的。您将 $errors 变量清空,然后所有发送电子邮件的逻辑都包裹在 if (empty($errors)) 条件中。删除 $errors 变量,删除那个 if-else 语句。不要在应用程序中留下没有实际作用的代码,这只会为您无故引入错误提供更多机会。
此外,虽然这只是一个小问题,但是您没有进行任何输入验证。如果提交到您的端点的 JSON 缺少某些数据,则脚本将崩溃。有人可能会在消息中插入 HTML,这可能是最好的恶心或最危险的情况。
您的脚本末尾还存在许多错误。
echo json_encode($response_array);
echo json_encode($from_email);
header($response_array);
return $from_email;

你正在将$response_array作为JSON输出到浏览器,然后在一个字符串($from_email)上运行json_encode,这甚至不会形成有效的JSON,两者的组合肯定也不会是有效的JSON。你应该只有一个echo json_encode,否则结果将不是有效的JSON,你会在你的angular前端得到一个解析错误。
接下来,你将你的$response_array传递给php的header函数。这对你来说肯定没有任何作用。header期望一个字符串,而不是一个数组,并且用于在HTTP响应中设置HTTP头键/值对。我无法想象你想要将$response_array中的任何数据设置为HTTP头响应值,即使你确实想要这样做,你也不能通过传递$response_array本身来实现它。因此,一定要删除这一行。PHP正默默地忽略它。
同样,没有理由返回任何东西。从被HTTP请求执行的文件中返回将没有任何影响。通常情况下,你不应该在函数之外返回(这不是一个函数)。虽然我不认为这行代码会导致任何错误,但它也不会做任何事情。如果它什么都不做,那就删除它。清楚地说,我指的是这一行代码:return $from_email;
这个脚本应该做的所有事情就是读取post数据,发送电子邮件,然后输出一个单独的json_encode调用。任何超过这个范围的内容都会导致无效的JSON,你的前端应用程序将无法读取。同样,使用curl(或其他类似工具)直接调用你的PHP脚本进行调试。这样你就可以看到它输出了什么,并验证它是否返回了正确的JSON。
现在,进入主要问题:缺乏发送电子邮件。你肯定有一些格式不正确的邮件头。每个邮件头都需要以\r\n结尾。你开始得很好,但你最后两行标题没有正确结束。这可能足以使你的电子邮件发送尝试失败。PHP内置的mail函数并不会很好地通知您错误,因此如果您在配置电子邮件时犯错误,您可能会更好地使用更强大的邮件程序。这将为您提供更好的反馈。在PHP中常见的一个是这个家伙:https://github.com/PHPMailer/PHPMailer
我建议你先修复你的电子邮件头,看看是否解决了问题。否则,你可能需要尝试使用实际的邮件发送器。原因是,电子邮件发送失效的另一个最常见原因是现代的垃圾邮件应对机制。PHP的mail函数会直接从服务器发送电子邮件。许多现代邮箱系统(特别是Gmail)将自动拒绝此类电子邮件,除非你发送的域名在DNS级别上得到正确配置。然而,你正在发送任意电子邮件地址(来自用户的$from_email变量内容)。现在很多电子邮件提供商都会自动拒绝这样的电子邮件,而PHP不会知道发生了什么,并且不会给出任何指示。
因此,建议你从一个你控制的固定地址发送邮件。可以通过在电子邮件消息中传递$from_email或将其设置为回复地址来实现。最好的方法是使用实际的电子邮件地址,并使用SMTP进行身份验证。Gmail可以很好地实现这一点。你应该能够找到一些使用上述PHPMailer与Gmail一起直接从你的Gmail地址发送电子邮件的示例。这将最小化被拒绝为垃圾邮件的几率,并为你提供额外的反馈(如果它在发送箱中但未显示,则被拒绝为垃圾邮件)。
现在,发送电子邮件已经变得棘手了。它不再像调用mail函数那样简单了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接