Merge pull request 'feat/send-mail-to-member' (#81) from feat/send-mail-to-member into master

Reviewed-on: #81
This commit is contained in:
Florent Le Saout 2024-03-20 14:04:38 +01:00
commit 9fd1712328
15 changed files with 224 additions and 121 deletions

View File

@ -1,12 +1,16 @@
# Prevent viewing of htaccess file.
<Files .htaccess>
order allow,deny
deny from all
<IfModule mod_access_compat.c>
Order Allow,Deny
Deny from all
</IfModule>
</Files>
# Prevent directory listings
Options All -Indexes
ErrorDocument 404 /404.html
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]
RewriteCond %{HTTP_HOST} ^astrolabe\.coop [NC]
RewriteRule ^ https://www.astrolabe.coop%{REQUEST_URI} [L,NE,R=301]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]
RewriteCond %{HTTP_HOST} ^astrolabe\.coop [NC]
RewriteRule ^ https://www.astrolabe.coop%{REQUEST_URI} [L,NE,R=301]
</IfModule>

View File

@ -21,6 +21,7 @@
</p>
{% endif %}
<ul class="social-links">
<li><a href="{{ [url , "/contact/"] | join | url }}" title="Écrire à {{ name }}" class="member-contact-at"><span>@</span></a></li>
{% if socialMastodon %}
<li><a href="{{ socialMastodon }}" title="mastodon"><svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M16.956 18.293c3.007-.36 5.625-2.212 5.954-3.905.519-2.667.476-6.508.476-6.508 0-5.207-3.411-6.733-3.411-6.733C18.255.357 15.302.025 12.233 0h-.075c-3.068.025-6.02.357-7.74 1.147 0 0-3.41 1.526-3.41 6.733 0 .315-.003.647-.004.993-.005.96-.01 2.024.018 3.136.123 5.091.933 10.11 5.64 11.355 2.171.575 4.035.695 5.535.613 2.722-.151 4.25-.972 4.25-.972l-.09-1.974s-1.945.613-4.13.538c-2.163-.074-4.448-.233-4.798-2.89a5.448 5.448 0 01-.048-.745s2.124.519 4.816.642c1.647.076 3.19-.096 4.759-.283zm2.406-3.705V8.283c0-1.288-.328-2.312-.987-3.07-.68-.757-1.57-1.145-2.674-1.145-1.278 0-2.246.491-2.885 1.474l-.623 1.043-.622-1.043c-.64-.983-1.608-1.474-2.886-1.474-1.104 0-1.994.388-2.674 1.146-.659.757-.987 1.781-.987 3.07v6.303h2.498V8.47c0-1.29.543-1.945 1.628-1.945 1.2 0 1.802.777 1.802 2.312v3.35h2.483v-3.35c0-1.535.601-2.312 1.801-2.312 1.086 0 1.629.655 1.629 1.945v6.119h2.497z"/></svg></a></li>
{% endif %}

View File

@ -1,9 +1,13 @@
{% from "macros/form.njk" import label, field, select, option, textarea, checkboxes, button %}
{% from "macros/form.njk" import label, field, select, option, textarea, checkboxes, button, hidden_field %}
<section class="[ form-container ]">
<svg aria-hidden="true" viewBox="0 0 1440 131" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M0 0h1440v131H0z"/><path d="M0 4.643l40-2.326c40-2.5 120-6.888 200 11.67 80 18.735 160 60.854 240 74.894 80 14.04 160 0 240-16.365 80-16.54 160-34.968 240-28.08 80 7.152 160 39.619 240 39.75 80-.131 160-32.598 200-49.139l40-16.365V131H0V4.643z" fill="#D6F253"/></svg>
{% if not contactMember %}
<svg aria-hidden="true" viewBox="0 0 1440 131" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M0 0h1440v131H0z"/><path d="M0 4.643l40-2.326c40-2.5 120-6.888 200 11.67 80 18.735 160 60.854 240 74.894 80 14.04 160 0 240-16.365 80-16.54 160-34.968 240-28.08 80 7.152 160 39.619 240 39.75 80-.131 160-32.598 200-49.139l40-16.365V131H0V4.643z" fill="#D6F253"/></svg>
{% endif %}
<div class="[ inner-wrapper ]">
<h2 id="contact-form" class="[ contact-heading ]">Nous contacter</h2>
{% if not contactMember %}
<h2 id="contact-form" class="[ contact-heading ]">Nous contacter</h2>
{% endif %}
<form name="contact" method="POST" action="/form/contact-form-handler.php">
<ol class="[ field-list ]">
<li class="[ field-list__field-group ]">
@ -16,20 +20,31 @@
</li>
<li class="[ field-list__field-group ] [ full-width ]">
{{ label("Je vous contacte pour :", "select") }}
{{ select( "select", [
{label: "Obtenir un rendez-vous (décrivez votre projet en quelques lignes)", value: "option 1"},
{label: "Obtenir des précisions sur le statut dentrepreneur salarié", value: "option 2"},
{label: "Proposer une mission à un coopérateur", value: "option 3"},
{label: "Proposer un partenariat", value: "option 4"}
], { required: true, options_before: [""], options_after: ["Autre demande"] } ) }}
{% if contactMember %}
{{ select( "select", [
{label: "Obtenir un rendez-vous (décrivez votre projet en quelques lignes)", value: "option 1"},
{label: "Proposer une mission à un coopérateur", value: "option 3"}
], { required: true, options_before: [""], options_after: ["Autre demande"] } ) }}
{% else %}
{{ select( "select", [
{label: "Obtenir un rendez-vous (décrivez votre projet en quelques lignes)", value: "option 1"},
{label: "Obtenir des précisions sur le statut dentrepreneur salarié", value: "option 2"},
{label: "Proposer une mission à un coopérateur", value: "option 3"},
{label: "Proposer un partenariat", value: "option 4"}
], { required: true, options_before: [""], options_after: ["Autre demande"] } ) }}
{% endif %}
</li>
<li class="[ field-list__field-group ] [ full-width ]">
{{ label("Votre message", "message") }}
{{ textarea( "message", { required: true, autocapitalize: "sentences", spellcheck: "true" } ) }}
</li>
<li class="[ field-list__field-group ] [ full-width ]">
{{ checkboxes("", "subscribe", [ "Je souhaite être tenu au courant de lactualité Astrolabe"], { description: "" } ) }}
</li>
{% if contactMember %}
{{ hidden_field('subscribe', '') }}
{% else %}
<li class="[ field-list__field-group ] [ full-width ]">
{{ checkboxes("", "subscribe", [ "Je souhaite être tenu au courant de lactualité Astrolabe"], { description: "" } ) }}
</li>
{% endif %}
<!-- H o n e y p o t -->
<li aria-hidden="true">
<label class="ohnohoney" for="name"></label>
@ -40,6 +55,9 @@
<input tabindex="-1" class="ohnohoney" autocomplete="off" type="email" id="email" name="email" placeholder="Your e-mail here">
</li>
</ol>
{% if contactMember %}
{{ hidden_field('contactTo', contactMember) }}
{% endif %}
{{ button("Envoyer") }}
</form>
</div>

View File

@ -1,102 +1,115 @@
<?php
require("/usr/share/php/libphp-phpmailer/autoload.php");
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$mail = new PHPMailer(true);
$errors = '';
$myEmail = getenv('ASTRO_SMTP_FROM');
if(empty($_POST['namezzz']) || empty($_POST['emailzzz']) || empty($_POST['message'])) {
$errors .= "\n Error: all fields are required";
}
if(!empty($_POST['name']) && !empty($_POST['email'])) {
$errors .= "\n Error: spam";
}
$name = $_POST['namezzz'];
$emailAddress = $_POST['emailzzz'];
$select = $_POST['select'];
$message = $_POST['message'];
$subscribe = $_POST['subscribe'];
if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
$errors .= "\n Error: Invalid email address $emailAddress";
}
if( empty($errors)) {
$to = $myEmail;
$emailSubject = "[Formulaire Astrolabe] Nouveau message";
switch ($select) {
case "option 1":
$purpose = "Demande de rendez-vous";
break;
case "option 2":
$purpose = "Demande de précisions sur le statut dentrepreneur salarié";
break;
case "option 3":
$purpose = "Proposition de misson";
break;
case "option 4":
$purpose = "Proposition de partenariat";
break;
default:
$purpose = "Autre demande";
}
$emailBody = "Vous avez reçu un nouveau message depuis le formulaire du site Astrolabe :".
"\r\n\r\nNom: $name \r\nEmail: $emailAddress \r\nRaison: $purpose\r\nSubscribe: $subscribe\r\n\r\n$message";
$emailBodyHTML = str_replace("\r\n", "<br>", $emailBody);
$mail->isSMTP();
$mail->Host = getenv('ASTRO_SMTP_HOSTNAME');
$mail->SMTPAuth = true;
$mail->Username = getenv('ASTRO_SMTP_USERNAME');
$mail->Password = getenv('ASTRO_SMTP_PASSWORD');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
//Options
$mail->CharSet = 'UTF-8';
$mail->WordWrap = 70;
//Recipients
$mail->setFrom($myEmail);
$mail->addAddress($myEmail);
$mail->addReplyTo($emailAddress, $name);
// Content
$mail->isHTML(true);
$mail->Subject = $emailSubject;
$mail->Body = $emailBodyHTML;
$mail->AltBody = $emailBody;
$mail->send();
// if subscribe add to mailing list
if(!empty($subscribe)) {
// process
// enovoi mail add to mailing list
}
// redirect to the 'thank you' page
header("Location: /thank-you/index.html");
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Contact form handler</title>
</head>
<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>
</body>
</html>
<?php
require("/usr/share/php/libphp-phpmailer/autoload.php");
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$mail = new PHPMailer(true);
$errors = '';
$myEmail = getenv('ASTRO_SMTP_FROM');
$myEmailSplitted = explode('@', $myEmail);
$domainFromMyEmail = (
empty($myEmailSplitted[1])
|| count($myEmailSplitted) != 2
) ? ''
: $myEmailSplitted[1];
$wantedContact = filter_input(INPUT_POST, 'contactTo', FILTER_SANITIZE_SPECIAL_CHARS);
$wantedContact = (
empty($wantedContact)
|| strpos($wantedContact, '@') !== false
|| strpos($wantedContact, '&') !== false
|| empty($domainFromMyEmail)
) ? $myEmail : "$wantedContact@$domainFromMyEmail" ;
if(empty($_POST['namezzz']) || empty($_POST['emailzzz']) || empty($_POST['message'])) {
$errors .= "\n Error: all fields are required";
}
if(!empty($_POST['name']) && !empty($_POST['email'])) {
$errors .= "\n Error: spam";
}
$name = $_POST['namezzz'];
$emailAddress = $_POST['emailzzz'];
$select = $_POST['select'];
$message = $_POST['message'];
$subscribe = $_POST['subscribe'];
if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
$errors .= "\n Error: Invalid email address $emailAddress";
}
if(empty($errors)) {
$emailSubject = "[Formulaire Astrolabe] Nouveau message";
switch ($select) {
case "option 1":
$purpose = "Demande de rendez-vous";
break;
case "option 2":
$purpose = "Demande de précisions sur le statut dentrepreneur salarié";
break;
case "option 3":
$purpose = "Proposition de misson";
break;
case "option 4":
$purpose = "Proposition de partenariat";
break;
default:
$purpose = "Autre demande";
}
$emailBody = "Vous avez reçu un nouveau message depuis le formulaire du site Astrolabe :".
"\r\n\r\nNom: $name \r\nEmail: $emailAddress \r\nRaison: $purpose\r\nSubscribe: $subscribe\r\n\r\n$message";
$emailBodyHTML = str_replace("\r\n", "<br>", $emailBody);
$mail->isSMTP();
$mail->Host = getenv('ASTRO_SMTP_HOSTNAME');
$mail->SMTPAuth = true;
$mail->Username = getenv('ASTRO_SMTP_USERNAME');
$mail->Password = getenv('ASTRO_SMTP_PASSWORD');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
//Options
$mail->CharSet = 'UTF-8';
$mail->WordWrap = 70;
//Recipients
$mail->setFrom($myEmail);
$mail->addAddress($wantedContact);
$mail->addReplyTo($emailAddress, $name);
// Content
$mail->isHTML(true);
$mail->Subject = $emailSubject;
$mail->Body = $emailBodyHTML;
$mail->AltBody = $emailBody;
$mail->send();
// if subscribe add to mailing list
if(!empty($subscribe)) {
// process
// enovoi mail add to mailing list
}
// redirect to the 'thank you' page
header("Location: /thank-you/index.html");
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Contact form handler</title>
</head>
<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>
</body>
</html>

41
src/members-contact.njk Normal file
View File

@ -0,0 +1,41 @@
---
title: 'Contacter un membre'
pagination:
data: collections.members
size: 1
alias: member
permalink: '/members/{{ member.fileSlug }}/contact/'
---
{% extends 'layouts/base.njk' %}
{% set memberData = member.data %}
{% set title = ["Écrire à ",memberData.name] | join %}
{% block content %}
<main id="main-content" tabindex="-1">
<section class="[ wrapper member ]">
<article>
<h1>{{ title }}</h1>
<p class="position">{{ memberData.position }}</p>
{% if memberData.positionInternal %}
<p>{{ memberData.positionInternal }}</p>
{% endif %}
<div class="[ member__wrapper ]">
<div class="member__info">
<img src="{{ memberData.profile }}" alt="photo de {{ memberData.name }}">
</div>
<div class="member__bio member-contact">
{% if memberData.emailSlug %}
{% set contactMember = memberData.emailSlug %}
{% else %}
{% set contactMember = member.fileSlug | replace("-",".") %}
{% endif %}
{% include "partials/components/contact-form.njk" %}
</div>
</div>
</article>
<a class="return-link" href="/equipe">Voir tous les membres</a>
</section>
</main>
{% endblock %}

View File

@ -8,6 +8,7 @@ personalSite: 'https://consometers.org/'
url: '/members/elias-martin-morisse'
socialLinkedin: 'https://www.linkedin.com/in/elias-martin-morisse-073a3247/'
socialMastodon: 'https://mamot.fr/@jaxom_kaplan'
emailSlug: 'elias.martin-morisse'
tags: [numérique, coopération, gestion-projet, libre, énergie, nextcloud]
location: [47.6514, -2.0839]
---

View File

@ -9,6 +9,7 @@ socialTwitter: 'https://twitter.com/AstrolabeCae'
socialLinkedin: 'https://www.linkedin.com/in/florentls/'
socialMastodon: 'https://framapiaf.org/@AstrolabeCAE'
url: '/members/florent-le-saout'
emailSlug: 'florent.lesaout'
tags: [ linux, dev, securité, libre, embarqué, gestion-projet, sensibilisation, education-populaire, animation, yocto, bootloader, FAE, CTS, gestion-client, C++, C, kernel]
location: [48.18163, -1.64052]
---

View File

@ -9,6 +9,7 @@ socialTwitter: 'https://twitter.com/JO_Interstices'
socialLinkedin: 'https://www.linkedin.com/in/jacques-olivier-farcy-3806121a2'
socialMastodon: 'https://mamot.fr/@Jolivier'
url: '/members/jacques-olivier-farcy'
emailSlug: 'jacques-olivier.farcy'
tags: [ conseil, numérique, level-designer ,visio, libre, open-source, sculpteur ]
location: [48.1113, -1.6792]
---

View File

@ -5,6 +5,7 @@ positionInternal: 'Membre'
date: '2023-07-01'
profile: '/images/profiles/jafm-profile.jpeg'
url: '/members/jaf-marchandise'
emailSlug: 'jacques-francois.marchandise'
tags: [Conseil, Recherche, Prospective, Exploranum, Numérique]
location: [47.70949, -3.34750]
---

View File

@ -6,6 +6,7 @@ date: '2020-12-01'
profile: '/images/profiles/jcp-profile.jpg'
socialLinkedin: 'https://www.linkedin.com/in/piriou-jean-christophe-9bb4bb3b/'
url: '/members/jean-christophe-piriou'
emailSlug: 'jean-christophe.piriou'
tags: [ sig, qgis, postgre, postgis, sql, gestion-projet]
location: [48.10451, -1.67977]
---

View File

@ -5,6 +5,7 @@ positionInternal: 'Support'
date: '2023-01-01'
profile: '/images/profiles/nlf-profile.jpg'
url: '/members/nelly-leflem'
emailSlug: 'contact'
tags: [ Comptabilité, Paie, Gestion, Tenue des comptes, Pack Libre, Silae, ExactOnline, EnDI ]
location: [48.1133,-1.6837]
---

View File

@ -7,6 +7,7 @@ profile: '/images/profiles/oriane-saintcyr-profile.jpg'
socialLinkedin: 'https://www.linkedin.com/in/oriane-sc/'
#socialMastodon: '
url: '/members/oriane-saint-cyr'
emailSlug: 'oriane.saint-cyr'
tags: [Numérique plus soutenable, Écologie, AMO, Numérique responsable, RSE, Reseau-Telecom]
location: [45.648377, 0.156237]
---

View File

@ -6,6 +6,7 @@ date: '2023-01-20'
profile: '/images/profiles/vlm-profile.jpg'
socialLinkedin: 'https://www.linkedin.com/in/valerie-le-merrer/'
url: '/members/valerie-le-merrer'
emailSlug: 'valerie.lemerrer'
tags: [ cybersécurité, analyse de Risque, audit, conseil, sensibilisation ]
location: [48.213983, -1.505285]
---

View File

@ -9,6 +9,7 @@ socialTwitter: 'https://twitter.com/YLeDuc'
socialLinkedin: 'https://www.linkedin.com/in/yleduc/'
socialMastodon: 'https://mastodon.top/@yleduc'
url: '/members/yannick-le-duc'
emailSlug: 'yannick.leduc'
tags: [ dev, entreprise, intuition, développement, conseil, creation, veille, AMOA, AMOE ]
location: [48.118, -1.6858]
---

View File

@ -45,6 +45,18 @@
svg > path {
fill: var(--color-secondary);
}
.member-contact-at {
text-decoration: none;
font-size: 1.7rem;
font-weight: 800;
&,
&:visited,
&:focus {
color: var(--color-secondary);
}
}
}
}
@ -56,7 +68,7 @@
margin-top: 1.5rem;
}
&::before {
&:not(.member-contact)::before {
content: '';
display: block;
position: absolute;
@ -67,6 +79,11 @@
top: -6rem;
left: -1.5rem;
}
&.member-contact .form-container {
border-radius: 1.75rem;
padding-top: 1.75rem;
}
}
}