dmdb/model/FormMail.cs

503 lines
26 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Reflection;
using System.Text;
namespace dezentrale.model
{
public class FormMail
{
public string To { get; set; } = "{Nickname} <{EMail}>";
public string Subject { get; set; }
public string Body { get; set; }
public FormMail() { }
public FormMail(FormMail copyFrom)
{
if(copyFrom != null)
{
this.To = copyFrom.To;
this.Subject = copyFrom.Subject;
this.Body = copyFrom.Body;
}
}
public FormMail ReplaceReflect(object o)
{
FormMail ret = new FormMail(this);
PropertyInfo[] objProperties = o.GetType().GetProperties();
foreach (var mailProperty in ret.GetType().GetProperties())
{
if (mailProperty.PropertyType != typeof(string)) continue;
if (!mailProperty.CanRead) continue;
if (!mailProperty.CanWrite) continue;
string propVal = (string)mailProperty.GetValue(ret, null);
if (propVal == null) continue;
bool changed = false;
foreach (var objProperty in objProperties)
{
if (!objProperty.CanRead) continue;
//check if objProperty occurs in mailProperty contents, then replace
string token = $"{{{objProperty.Name}}}";
string tokenValue;
try
{
tokenValue = objProperty.GetValue(o, null).ToString();
} catch(NullReferenceException)
{
//Console.WriteLine($"FormMail.ReplaceReflect({o}): property {token}: {ex.Message}");
continue;
}
if (propVal.Contains(token))
{
//NOTE: This is problematic because it allows the user to generate recursive replacements by setting e.g. the Nickname to "{PgpFingerprint}"
propVal = propVal.Replace(token, tokenValue);
changed = true;
}
}
if (changed)
{
mailProperty.SetValue(ret, propVal, null);
}
}
return ret;
}
public LogSubEvent Send(object replaceReflect = null, List<string> files = null)
{
FormMail src = replaceReflect == null ? this : ReplaceReflect(replaceReflect);
LogSubEvent ret = new LogSubEvent()
{
Type = LogEvent.eEventType.EMail,
Topic = src.Subject,
Details = $"From: {Program.config.Smtp.From}\nTo: {src.To}\n\nBody:\n{src.Body}",
};
try
{
if (!Program.config.Smtp.Enabled)
{
throw new Exception("FormMail.Send() Error: SMTP is disabled!");
}
//Build up Mail Message
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress(Program.config.Smtp.From);
message.From = fromAddress;
message.To.Add(new MailAddress(src.To));
if (!string.IsNullOrEmpty(Program.config.Smtp.CcTo))
message.CC.Add(new MailAddress(Program.config.Smtp.CcTo));
message.SubjectEncoding = Encoding.UTF8;
message.BodyEncoding = Encoding.UTF8;
//For spam reasons, we need to include an User-Agent and a valid message ID
//string mid;
//message.Headers.Add("User-Agent", $"dezentrale-members ver. {Program.VersionNumber} https://hg.macht-albern.de/dezentrale-members/");
//message.Headers.Add("User-Agent", @"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 Lightning/6.2.7");
message.Headers.Add("Message-Id",
$"<{Guid.NewGuid()}@{fromAddress.Host}>");
//System.Windows.Forms.MessageBox.Show($"Message-Id: {mid}");
message.Subject = src.Subject;
message.Body = src.Body;
if (files != null)
foreach (string f in files)
message.Attachments.Add(new Attachment(f));
SmtpClient client = new SmtpClient(Program.config.Smtp.Host, Program.config.Smtp.Port)
{
DeliveryMethod = SmtpDeliveryMethod.Network,
EnableSsl = Program.config.Smtp.SSL,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential(Program.config.Smtp.UserName, Program.config.Smtp.Password),
};
client.Send(message);
//client.Send(Program.config.Smtp.From, src.To, src.Subject, src.Body);
} catch(Exception ex)
{
Console.WriteLine($"FormMail.Send() Error:\n{ex.Message}\n");
ret.Type = LogEvent.eEventType.Error;
}
return ret;
}
public static FormMail GenerateNewMemberWelcome()
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Willkommen in der dezentrale, {Nickname}! Welcome to the dezentrale, {Nickname}",
Body = "Hallo {Nickname}!\n"
+ "\n"
+ "Willkommen im dezentrale Hackspace.\n"
+ "Deine Mitgliedsnummer ist {NumberString}.\n"
+ "Bitte benutze diese Nummer im Betreff von Überweisungen der Mitgliedsbeiträge. Die Höhe deines monatlichen Beitrages ist {PaymentAmountString} {PaymentAmountCurrency}.\n"
+ "Dein Mitgliedsaccount ist aktiv nach 7 Tagen und dem Eingang des ersten Mitgliedsbeitrages.\n"
+ "\n"
+ "\n"
+ "\n"
+ "Hello {Nickname}!\n"
+ "\n"
+ "Welcome to the dezentrale hackspace.\n"
+ "Your membership number is {NumberString}.\n"
+ "Please use this number in the topic of the bank wire transfers of your membership fees. The monthly amount is {PaymentAmountString} {PaymentAmountCurrency}.\n"
+ "Your membership account is active after 7 days, and after you paid the first membership fee.\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateMemberAccountActivated()
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Dein Mitgliedsaccount wurde aktiviert, {Nickname}! Your membership account is now active, {Nickname}",
Body = "Hallo {Nickname}!\n"
+ "\n"
+ "Dein Mitgliedsaccount ist nun aktiv.\n"
+ "Um die Tür zum Gebäude zu öffnen, kannst du den Schlüssel"
+ " aus dem Tresor verwenden. Dieser befindet sich"
+ " an der Fahrrad-Wand ganz links in der Ecke.\n"
+ "Die Kombination für das Schloss lautet: {KeylockCombination}.\n"
+ "Das Tor zum Innenhof kann man öffnen, indem man\n"
+ "- 1x klingelt, wenn der Space auf ist (Logo leuchtet) oder\n"
+ "- 3x klingelt, wenn der Space zu ist (direkt 3x hintereinander, während es noch klingelt)\n"
+ "Für weitere Fragen per E-Mail kannst du dich an unsere Mailinglisten wenden:\n"
+ "Die discuss-Liste ist für alle offen: discuss@dezentrale.space\n"
+ "Die member-Liste ist für Kommunikation zwischen den Mitgliedern: members@dezentrale.space\n"
+ "Für organisatorisches gibt es die Vorstands-Mailingliste: vorstand@dezentrale.space\n"
+ "Note: Möglicherweise ist deine Registrierung"
+ " auf der members-Liste zu diesem Zeitpunkt noch nicht abgeschlossen.\n"
+ "Siehe auch: https://lists.dezentrale.space/mailman/listinfo\n"
+ "\n"
+ "\n"
+ "\n"
+ "Hello {Nickname}!\n"
+ "\n"
+ "Your member account is now active.\n"
+ "To open the building door, you can use the key from the tresor.\n"
+ "It is located in the corner at the left of the bicycle-wall.\n"
+ "The combination for the number lock is: {KeylockCombination}.\n"
+ "You can open the door to the courtyard by\n"
+ "- ringing the doorbell once, if the space is open (logo is turned on)\n"
+ "- ringing 3 times, if the space is closed (push 3 times directly, while it's still ringing)\n"
+ "For further questions via E-Mail, you can use our mailing lists:\n"
+ "The discuss list is open for everyone: discuss@dezentrale.space\n"
+ "The member list is used for communication between members: members@dezentrale.space\n"
+ "For organisational requests, there is the vorstand list: vorstand@dezentrale.space\n"
+ "Note: Probably, your registration at the members list isn't finished at this point in time\n"
+ "See also: https://lists.dezentrale.space/mailman/listinfo\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateNewMemberVorstand()
{
return new FormMail()
{
To = "{VSName} <{VSEmail}>",
Subject = "Neuer Mitgliedsantrag, Nummer = {NumberString}, nick = {Nickname}!",
Body = "Hallo Vorstandsliste,\n"
+ "\n"
+ "Folgender Nutzer wurde in die Datenbank aufgenommen.\n"
+ "Mitgliednummer: {NumberString}\n"
+ "Nickname: {Nickname}\n"
+ "Realname: {FirstName} {LastName}\n"
+ "EMail: {EMail}\n"
+ "\n"
+ "Damit beginnt eine 7-Tage-Einspruchsfrist für den Vorstand.\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateMemberAccountVorstand()
{
return new FormMail()
{
To = "{VSName} <{VSEmail}>",
Subject = "Mitgliedsaccount aktiv, Nummer = {NumberString}, nick = {Nickname}!",
Body = "Hallo Vorstandsliste,\n"
+ "\n"
+ "Der Mitgliedsaccount ist nun aktiv:\n"
+ "Mitgliednummer: {NumberString}\n"
+ "Nickname: {Nickname}\n"
+ "EMail: {EMail}\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateAutoTypeFoerdermitglied()
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Mitgliedschaft geändert in \"Fördermitglied\"",
Body = "Hallo {Nickname},!\n"
+ "\n"
+ "Dein Mitgliedsstatus bei uns war bisher \"reguläres Mitglied\".\n"
+ "Da du zu den letzten beiden Mitgliedsversammlungen nicht anwesend warst,"
+ " wurde dein Status automatisch zu \"Fördermitglied\" geändert.\n"
+ "\n"
+ "Für dich bedeutet dies keinerlei Änderungen. Die Beschlussfähigkeit"
+ " zukünftiger Mitgliedsversammlungen kann auf diese Weise besser erreicht werden.\n"
+ "\n"
+ "Du kannst zu diesen Versammlungen als Gast anwesend sein oder deinen Status zum Anfang"
+ " der MV wieder auf \"reguläres Mitglied\" ändern.\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateManualTypeChanged()
{
//Regular / Foerdermitglied
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Mitgliedschaft geändert in \"{Type}\". Membership type changed to \"{Type}\"",
Body = "Hallo {Nickname},!\n"
+ "\n"
+ "Deine Mitgliedschaft bei uns wurde manuell geändert zu \"{Type}\".\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "\n"
+ "Your membership type was changed manually to \"{Type}\".\n"
+ "\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateBalanceNegativeMemberNotify1()
{
//Konto im Minus zw. -2x Beitrag und 0
//Achtung: xx euro im Minus, bei 2 Monaten Zahlungsverzug wird dein Account deaktiviert
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Beitragskonto im negativen Bereich. Membership fee balance is negative.",
Body = "Hallo {Nickname},!\n"
+ "\n"
+ "Dein Konto für Mitgliedsbeiträge ist im negativen Bereich:\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "Bitte bezahle deine Mitgliedsbeiträge.\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "\n"
+ "Your membership account balance is negative:\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Account balance: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "Please pay your membership fee.\n"
+ "\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateBalanceNegativeMemberNotify2()
{
//Konto im Minus < -2x Beitrag
//Achtung: 2 Monate im Verzug, Account wird zum Ende des Monats deaktiviert
//xx euro im Minus
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Beitragskonto im negativen Bereich. Membership fee balance is negative.",
Body = "Hallo {Nickname},!\n"
+ "\n"
+ "Dein Konto für Mitgliedsbeiträge ist im negativen Bereich:\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "Bitte bezahle deine Mitgliedsbeiträge.\n"
+ "\n"
+ "Hinweis: Zum Ende des Monats wird dein Mitgliedsaccount deaktiviert.\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "\n"
+ "Your membership account balance is negative:\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Account balance: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "Please pay your membership fee.\n"
+ "\n"
+ "Note: At the end of the month, your membership account will be disabled.\n"
+ "\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateBalanceNegativeMemberDeactivation()
{
//Konto im Minus < -2x Beitrag
//Konto wird nun deaktiviert --> member.
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Dein Mitgliedsaccount wurde deaktiviert. Your membership account was disabled.",
Body = "Hallo {Nickname},\n"
+ "\n"
+ "Dein Mitgliedsaccount wurde wegen fehlender Beitragszahlungen deaktiviert.\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "Bitte wende dich zur Klärung der Sache an: {VSName} <{VSEmail}>\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},\n"
+ "\n"
+ "Your membership account was disabled due to lack of payments.\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Account balance: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "To settle this issue, please contact: {VSName} <{VSEmail}>\n"
+ "\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
public static FormMail GenerateBalanceNegativeMemberDeactivationVS()
{
//Konto im Minus < -2x Beitrag
//Konto wird nun deaktiviert --> vorstand.
return new FormMail()
{
To = "{VSName} <{VSEmail}>",
Subject = "Mitgliedsaccount wurde deaktiviert, Nummer = {NumberString}, nick = {Nickname}!",
Body = "Hallo Vorstandsliste,\n"
+ "\n"
+ "Folgender Nutzer wurde mangels Beitragszahlung in der Datenbank deaktiviert.\n"
+ "Mitgliednummer: {NumberString}\n"
+ "Nickname: {Nickname} <{EMail}>\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateBalanceNegativeNotify2SM()
{
//Konto im Minus < -2x Beitrag
//Achtung: Mitglied ist 2 Monate im Verzug, Account wird zum Ende des Monats deaktiviert
//xx euro im Minus
return new FormMail()
{
To = "schatzmeister <sm@example.com>", //to be replaced!
Subject = "Konto eines Mitgliedes ist <= -2 Monatsbeiträge.",
Body = "Hallo Schatzmeister,\n"
+ "\n"
+ "Folgender Nutzer hat mangels Beitragszahlungen einen negativen Kontostand.\n"
+ "Mitgliednummer: {NumberString}\n"
+ "Nickname: {Nickname} <{EMail}>\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateBalanceAbove200NotifySM()
{
//Konto > 200 EUR
return new FormMail()
{
To = "schatzmeister <sm@example.com>", //to be replaced!
Subject = "Konto eines Mitgliedes ist > 200 Euro.",
Body = "Hallo Schatzmeister,\n"
+ "\n"
+ "Folgender Nutzer hat sehr viel in sein Mitgliedskonto eingezahlt.\n"
+ "Mitgliednummer: {NumberString}\n"
+ "Nickname: {Nickname} <{EMail}>\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
+ "Kontostand: {AccountBalanceString} {PaymentAmountCurrency}\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateMemberPaymentNotify(bool odd)
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "dezentrale - Mitgliedsbeitrag erhalten",
Body = "Hallo {Nickname}!\n"
+ "\n"
+ "Dein Mitgliedsbeitrag ist angekommen. Vielen Dank.\n"
+ "\n"
+ "\nEingangsdatum: {ValutaDate}\n"
+ "Betrag: {AmountString} {Currency}\n"
+ (odd ? "Hinweis: Der Betrag passt nicht zum eingestellten Mitgliedsbeitrag ({PaymentAmountString} " + Program.config.RegularPaymentCurrency + ")\n" : "\n")
+ "\n"
+ "Der nächste Mitgliedsbeitrag ist damit fällig am Anfang des Monats {PaymentDueMonth} (AccountBalance = {AccountBalanceString})\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateKeylockChanged()
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "dezentrale - Schlosscode hat sich geändert",
Body = "Hallo {Nickname}!\n"
+ "\n"
+ "Der Schlosscode für den Schlüsseltresor hat sich geändert.\n"
+ "Die neue Kombination lautet {KeylockCombination}\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateTestmail()
{
return new FormMail()
{
To = "{EMailName} <{EMail}>",
Subject = "dezentrale-members - Testmail",
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dies ist ein Test der Mail-Einstellungen von dezentrale-members.\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
}
}