I'm on a private php heroku repo, and want to create a form that can allow users on my website to input their email address and submit the form and add the email to an existing mailing list on mailgun.
I've contacted MailGun support, they've said its possible and to look at the documentation.
The docs are vague, I can't figure it out on my own.
Is there code examples you can give me that may point me in the right direction?
This is the line of thought:
* Step 1 - Create a mailinglist that will contain your list of emails.
* Step 2 - Create a form that asks a user for his email address, asks him to confirm the use of his email, sends an email address to the given address to confirm subscription.
*
Step 1
# Include the Autoloader file (see documentation on how to install the php wrapper)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client. Use your APIKey
$mgClient = new Mailgun('key-3ax6xnjp29jd6fds4gc373sgvjxteol0l');
# Issue the call to the client.
$result = $mgClient->post("lists", array(
'address' => 'my-user-list#mydomain.org',
'description' => 'A List of users'
));
This creates a list named 'A list of users' and is reachable internally using 'my-user-list#mydomain.org'
** Step 2 **
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Widget</title>
</head>
<body>
<form action="contact.php" method="POST" onsubmit="return check_the_box()">
<input name="email" type="text" required="yes">
I've read and agree to the ToS
<input id="chx" type="checkbox">
<button type="submit" >Submit</button>
<span style="display: none" id="pls"> Please check the Terms of Service box</span>
</form>
<script type="text/javascript">
var box = document.getElementById("chx");
var alrt = document.getElementById("pls");
function check_the_box(){
if(!box.checked) {
alrt.setAttribute("style","display: inline");
return false
}
else {
return true
}
}
</script>
</body>
</html>
Then you need to capture the fields from this form and send an email:
# Include the Autoloader require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = new Mailgun('key-3ax6xnjp29jd6fds4gc373sgvjxteol0l');
$domain = "mydomain.org";
# Make the call to the client.
$result = $mgClient->sendMessage($domain, array(
'from' => 'YOU#mydomain.org',
'to' => 'GUYWHOSIGNEDUP#hisdomain.com',
'subject' => 'Confirmation Email',
'html' => 'Please, click this link to confirm you want to be part of my list <a href=\'http://website.com/confirmation.php?authcode=SOMEGENERATEDSTRING\'> CONFIRM </a>'
));
Create a generated string for each email address
The user will click on the link and will be redirected and finally added to the mailing list:
Step 3
Adding to mailing list
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = new Mailgun('key-3ax6xnjp29jd6fds4gc373sgvjxteol0l');
$listAddress = 'my-user-list#mydomain.org';
# Issue the call to the client.
$result = $mgClient->post("lists/$listAddress/members", array(
'address' => 'GUYWHOSIGNEDUP#hisdomain.com',
'description' => 'Signed up',
'subscribed' => true,
));
Done!
All you need to do is create the generation code that is unique to every user, did something like that:
function makeConfirmation($newguy) {
$confirmCode = md5($newguy.'somestringonlyknowntome');
return $confirmCode;
}
And finally before adding him to the mailing list I confirm the parameter sent to my server in the URL when he clicked the confirmation email
function checkConfirmation($conf,$email) {
if($conf== md5($email.'somestringonlyknowntome')) {
return true;
} else { return false; }
}
Edit accordingly..
Additionally:
Here's a good tutorial for you to follow available on Mailgun's github repository in PHP.
Tutorial for OPTins
Good luck and let me know if you succeeded! :)
I'd love to hear from you and write a blog about this on mailgun!
Related
I Want to develop a flask navigation bar like Google Contacts.
I Want to Render a particular HTML page inside the red box (as in the picture) when I click each of the navigation buttons (the green box as in picture) without refreshing the page.
I have already tried using
{% extends "layout.html" %}
As #Klaus D. mentioned in the comments section, what you want to achieve can be done using Javascript only. Maybe your question were
How can I send a request to my server-side (to get or fetch some information) and receive back a response on the client-side without having to refresh the page unlike the POST method usually does?
I will try to address the aforementioned question because that's probably your case.
A potential solution
Use Ajax for this. Build a function that sends a payload with certain information to the server and once you receive back the response you use that data to dynamically modify the part of the web-page you desire to modify.
Let's first build the right context for the problem. Let's assume you want to filter some projects by their category and you let the user decide. That's the idea of AJAX, the user can send and retrieve data from a server asynchronously.
HTML (div to be modified)
<div class="row" id="construction-projects"></div>
Javascript (Client-side)
$.post('/search_pill', {
category: category, // <---- This is the info payload you send to the server.
}).done(function(data){ // <!--- This is a callback that is being called after the server finished with the request.
// Here you dynamically change parts of your content, in this case we modify the construction-projects container.
$('#construction-projects').html(data.result.map(item => `
<div class="col-md-4">
<div class="card card-plain card-blog">
<div class="card-body">
<h6 class="card-category text-info">${category}</h6>
<h4 class="card-title">
${item.title_intro.substring(0, 40)}...
</h4>
<p class="card-description">
${item.description_intro.substring(0, 80)}... <br>
Read More
</p>
</div>
</div>
</div>
`))
}).fail(function(){
console.log('error') // <!---- This is the callback being called if there are Internal Server problems.
});
}
Build a function that will fetch the current page via ajax, but not the whole page, just the div in question from the server. The data will then (again via jQuery) be put inside the same div in question and replace old content with new one.
Flask (Server-side)
''' Ajax path for filtering between project Categories. '''
#bp.route('/search_pill', methods=['POST'])
def search_pill():
category = request.form['category']
current_page = int(request.form['current_page'])
## Search in your database and send back the serialized object.
return jsonify(result = [p.serialize() for p in project_list])
Thank you #CaffeinatedCod3r,#Klaus D and #newbie99 for your answers.
I Figured it out. instead of using Flask we can use Angular JS Routing for navigation.
Here is the example that i referred:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<head>
<base href="/">
</head>
<body ng-app="myApp">
<p>Main</p>
Banana
Tomato
<p>Click on the links to change the content.</p>
<p>Use the "otherwise" method to define what to display when none of the links are clicked.</p>
<div ng-view></div>
<script>
var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/banana", {
template : "<h1>Banana</h1><p>Bananas contain around 75% water.</p>"
})
.when("/tomato", {
template : "<h1>Tomato</h1><p>Tomatoes contain around 95% water.</p>"
})
.otherwise({
template : "<h1>Nothing</h1><p>Nothing has been selected</p>"
});
$locationProvider.html5Mode(true);
});
</script>
</body>
</html>
By Using $locationProvider.html5Mode(true) i was able to remove the # from the URL.
Trying to work out accept.js to replace a depreciated method for authorize.net payments. Not doing anything gcomplicated, but can't get past the authentication failed message when using the sandbox
Logging into the sandbox account to generate keys … they're named slightly differently than the code samples. So I MAY BE AN IDIOT.
OK, apiLoginID - obvious …
Code below calls for data-clientKey. Not 100% sure which of the two below that actually is. I've tried both. Same error with both.
API Login ID : 4CLLpD------
Transaction Key : 9628s6xCSh------
Key : ------A4D932A4AFED546DE55E4D04C16CA66549915AFDC4FBA3A1665E271A2FB48A7A34394843A47BC170FFB4A5B99EDD17B75D99942E4E7F7133C2E1------
<script type="text/javascript"
src="https://jstest.authorize.net/v3/AcceptUI.js"
charset="utf-8">
</script>
<form id="paymentForm"
method="POST"
action="mysite.com/beta-account/order-receipt.php" >
<input type="hidden" name="dataValue" id="dataValue" />
<input type="hidden" name="dataDescriptor" id="dataDescriptor" />
<button type="button"
class="AcceptUI btn-success btn-lg"
data-billingAddressOptions='{"show":true, "required":false}'
data-apiLoginID="4CLLpDX----"
data-clientKey="9628s6xCShc-----"
data-acceptUIFormBtnTxt="Submit"
data-acceptUIFormHeaderTxt="Card Information"
data-responseHandler="responseHandler">Pay
</button>
</form>
<script type="text/javascript">
function responseHandler(response) {
if (response.messages.resultCode === "Error") {
var i = 0;
while (i < response.messages.message.length) {
console.log(
response.messages.message[i].code + ": " +
response.messages.message[i].text
);
i = i + 1;
}
} else {
paymentFormUpdate(response.opaqueData);
}
}
function paymentFormUpdate(opaqueData) {
document.getElementById("dataDescriptor").value = opaqueData.dataDescriptor;
document.getElementById("dataValue").value = opaqueData.dataValue;
document.getElementById("paymentForm").submit();
}
</script>
Right now, there's not really anything on the order-receipt.php page. I'm just trying to get the post to make it that far and show me a dump of everything that post to the page, so even once I get this working, I've still got a ways to go.
When I go to the payment page, hit the "Pay" button, fill out the credit card form, hit "submit" … it doesn't go anywhere at all. It stays on the page and the console reports: "E_WC_21: User authentication failed due to invalid authentication values."
This has turned into one more frustrating thing after pulling over half my hair out over authorize.net's documentation of what I need to do about the MD5 end-of-life … of which I never could get anything to work to replace the SIM relay-response method that was being used. response.js seems fairly simple as a replacement, and I'm stuck here too.
What do I try next?
OK, I think I found the problem …
There's a difference between the API Login ID, the Transaction Key, and the Client Key.
That's not immediately obvious in some of the docs ….
For getting the data-clientKey, you should go to this place. Please see the attach screenshot.
Screenshot
I am submitting a form that passes three values to the controller, which are email, fullname and id fields.
#using (Html.BeginForm("SubmitResult", "TestAPI", FormMethod.Post, new { id = "postEmailForm" }))
{
<div id="details-container">
<input type="text" name="email" />
<input type="text" name="fullName" />
<input type="text" name="studentId" />
<button type="submit" id="send">Send</button>
</div>
}
Controller:
[HttpPost("SubmitResult/{email}/{fullName}/{studentId}")]
[Authorize(Roles = "Admin, Shop")]
public IActionResult SubmitResult(string email, string fullName, long? studentId)
{
}
However, when I click on submit button, it throws an error message in the console.
OPTIONS https://localhost:50138/TestAPI/SubmitResult
net::ERR_SSL_PROTOCOL_ERROR.
Headers:
Request URL: https://localhost:50138/TestAPI/SubmitResult
Referrer Policy: no-referrer-when-downgrade
How do I properly decorate the attribute in the controller, so I can pass multiple parameters to test API using Postman?
I was expecting something like below to work for testing.
http://localhost:50138/api/TestAPI/SubmitResult/test#gmail.com/MikeShawn/2
There are few issues with your code.
First issue is that it looks like when you post the data it tries to send it using a cross-origin request. If this is on purpose then you have to add CORS middleware in your pipe. If not - you have to figure out why it happens and fix it. There are not enough details in your question to say why it happens.
Two URLs have the same origin if they have identical schemes, hosts, and ports.
Second issue is that you are trying to send data by adding parameters to URL. This is wrong because the data will be sent in the request body. So regarding HttpPost attribute it should look like this:
[HttpPost]
[Authorize(Roles = "Admin, Shop")]
public IActionResult SubmitResult(string email, string fullName, long? studentId)
{
}
UPDATE
Just looked at your question again. It seems the page with form itself was opened using http scheme, but the POST request is actually going to https scheme. So to resolve first issue make sure that page with form is loaded using https scheme too.
Using Symfony 2.3.4.
When I create a form with a field in it that's supposed to process emails I go and use the default email type:
builder->add('email', 'email', array(
'label' => 'Email',))
with only this, it successfully validates user inputs, only not the way I want, meaning:
how it works:
me --> notallowed
me#gmail --> allowed
how I need it to work:
me --> notallowed
me#gmail --> notallowed
me#gmail.com --> allowed
summing up:
I figured what I need is to change/customize the default regex that validates this which I guess is deep in one of the many files in symfony.
appreciate any tips regarding this, thanks
Actually, the validation that you are seeing here is the browser based HTML5 validation. The message that pops up if me is entered comes right from your browser, no Symfony involved. I find HTML5 validation unreliable for the most part. Best practice is to validate on the server side, and use some type of javascript validation for the client side.
for more info on setting up server side validation, see the symfony docs, they give some great examples and it is very useful.
You can handle email validation by javascript . Call any method on form submit like
function validate(){
var email=$('#email').val();
if(email!=""){
var re =/^([a-zA-Z0-9_\.\-])+\#(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (!re.test(email)) {
alert('please Enter Valid email address');
}
}
<form onSubmit="return validate();">
<input type="text" name="email" id="email" placeholder="Please Enter your Email address" />
</form>
Please refer this following link for form field type email
Symfony form type email
If you want jquery validation for email
$('#formId').validate({
errorClass: 'help-block',
rules: {
'textFieldName': {
required: true,
email: true
}
},
messages: {
'textFieldName': {
email: "Invalid Email Address"
}
},
highlight: function (element) {
$(element).parent().parent().removeClass("success").addClass("error");
},
unhighlight: function (element) {
$(element).parent().parent().removeClass("error").addClass("success");
}
}); // validate
I am trying to create a Zend_Controller_Router_Route_Regex route to process URLs in the following form:
search?q=chicken/page=2 where the first regex subpattern would be chicken and second one would be 2. As for the second part where page=2, I want to make it optional if it is the first page, that is page=1. So another url such as search?q=chicken would also be valid and is equivalent to search?q=chicken/page=1.
Here is my attempt albeit without any success, but to give you a better picture of what I am trying to do.
$route = new Zend_Controller_Router_Route_Regex(
'search\?q=([a-zA-Z0-9]+)(?:/page=(\d+))',
array(
'page'=> '1',
'module' => 'default',
'controller' => 'search',
'action' => 'index' ),
array( 1 => 'query', 2 => 'page' ),
'search?=%s/page=%d');
$router->addRoute('search', $route);
The problem here is I cant compose the correct regex.
Thanks in advance.
EDIT #1
The correct regex, as pointed out by MA4, is 'search\?q=([a-zA-Z0-9]+)(?:/page=(\d+))?'
The real problem is pointed by Darryl. Here is a little bit more info to put things into perspective.
My search text box and button
<form action="/search" method="get">
<input type="text" name="q" />
<input type="submit" value="Search" />
</form>
Every time I press the search button, I get the search?q=[text] request. How do I force it to go through the regex match route?
Here is what i want to do, however the code does not work
if($this->getRequest()->getParam('query')){
// redirect success
} else {
$url = "search?q=" . $this->_getParam('q');
$this->_redirect(route('search'), array('code' => 301 ));
}
/search?q=chicken/page=2 is not parsable by Zend Frameworks' router. The router will only see /search.
The router relies on the Path Info provided by the server and anything after the ? is the query string.
You would need to use a path such as this:
/search/[word] (default page 1)
/search/[word]/[page]
In which case your regex would become much simpler.
make the second part optionnal by adding a ? after it:
search\?q=([a-zA-Z0-9]+)(?:/page=(\d+))?