Convert spam letters to a LocalizedDataset (#36393)

* Convert spam letters to a LocalizedDataset

* Error -> warning

* Comments

* Add migrations for old spam mail entities
This commit is contained in:
Tayrtahn
2025-04-14 13:38:21 -04:00
committed by GitHub
parent e7dfb66def
commit 110ed2736f
7 changed files with 236 additions and 253 deletions

View File

@@ -4,18 +4,22 @@ using Content.Shared.UserInterface;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Random.Helpers;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Tag; using Content.Shared.Tag;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using static Content.Shared.Paper.PaperComponent; using static Content.Shared.Paper.PaperComponent;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Shared.Paper; namespace Content.Shared.Paper;
public sealed class PaperSystem : EntitySystem public sealed class PaperSystem : EntitySystem
{ {
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!; [Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
@@ -27,6 +31,8 @@ public sealed class PaperSystem : EntitySystem
private static readonly ProtoId<TagPrototype> WriteIgnoreStampsTag = "WriteIgnoreStamps"; private static readonly ProtoId<TagPrototype> WriteIgnoreStampsTag = "WriteIgnoreStamps";
private static readonly ProtoId<TagPrototype> WriteTag = "Write"; private static readonly ProtoId<TagPrototype> WriteTag = "Write";
private EntityQuery<PaperComponent> _paperQuery;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -38,7 +44,11 @@ public sealed class PaperSystem : EntitySystem
SubscribeLocalEvent<PaperComponent, InteractUsingEvent>(OnInteractUsing); SubscribeLocalEvent<PaperComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<PaperComponent, PaperInputTextMessage>(OnInputTextMessage); SubscribeLocalEvent<PaperComponent, PaperInputTextMessage>(OnInputTextMessage);
SubscribeLocalEvent<RandomPaperContentComponent, MapInitEvent>(OnRandomPaperContentMapInit);
SubscribeLocalEvent<ActivateOnPaperOpenedComponent, PaperWriteEvent>(OnPaperWrite); SubscribeLocalEvent<ActivateOnPaperOpenedComponent, PaperWriteEvent>(OnPaperWrite);
_paperQuery = GetEntityQuery<PaperComponent>();
} }
private void OnMapInit(Entity<PaperComponent> entity, ref MapInitEvent args) private void OnMapInit(Entity<PaperComponent> entity, ref MapInitEvent args)
@@ -203,6 +213,30 @@ public sealed class PaperSystem : EntitySystem
UpdateUserInterface(entity); UpdateUserInterface(entity);
} }
private void OnRandomPaperContentMapInit(Entity<RandomPaperContentComponent> ent, ref MapInitEvent args)
{
if (!_paperQuery.TryComp(ent, out var paperComp))
{
Log.Warning($"{EntityManager.ToPrettyString(ent)} has a {nameof(RandomPaperContentComponent)} but no {nameof(PaperComponent)}!");
RemCompDeferred(ent, ent.Comp);
return;
}
var dataset = _protoMan.Index(ent.Comp.Dataset);
// Intentionally not using the Pick overload that directly takes a LocalizedDataset,
// because we want to get multiple attributes from the same pick.
var pick = _random.Pick(dataset.Values);
// Name
_metaSystem.SetEntityName(ent, Loc.GetString(pick));
// Description
_metaSystem.SetEntityDescription(ent, Loc.GetString($"{pick}.desc"));
// Content
SetContent((ent, paperComp), Loc.GetString($"{pick}.content"));
// Our work here is done
RemCompDeferred(ent, ent.Comp);
}
private void OnPaperWrite(Entity<ActivateOnPaperOpenedComponent> entity, ref PaperWriteEvent args) private void OnPaperWrite(Entity<ActivateOnPaperOpenedComponent> entity, ref PaperWriteEvent args)
{ {
_interaction.UseInHandInteraction(args.User, entity); _interaction.UseInHandInteraction(args.User, entity);

View File

@@ -0,0 +1,17 @@
using Content.Shared.Dataset;
using Robust.Shared.Prototypes;
namespace Content.Shared.Paper;
/// <summary>
/// If added to an entity that has a <see cref="PaperComponent"/>, the name,
/// description and contents of the paper will be replaced with a random
/// entry from the specified <see cref="LocalizedDatasetPrototype"/>.
/// Requires <see cref="PaperComponent"/>.
/// </summary>
[RegisterComponent]
public sealed partial class RandomPaperContentComponent : Component
{
[DataField(required: true)]
public ProtoId<LocalizedDatasetPrototype> Dataset;
}

View File

@@ -1,6 +1,8 @@
# All spelling mistakes and broken english are intentional! # All spelling mistakes and broken english are intentional!
# I hate saving paper contents in ftl files # I hate saving paper contents in ftl files
## Headers and reusable elements
-delivery-header-nanotrasen = [color=blue] -delivery-header-nanotrasen = [color=blue]
╔══════════════════╗ ╔══════════════════╗
║███░███░░░░██░░░░░║ ║███░███░░░░██░░░░░║
@@ -28,8 +30,11 @@
║░░░░░████████░░░░░║ ║░░░░░████████░░░░░║
╚══════════════════╝[/color] ╚══════════════════╝[/color]
## Spam letters
delivery-spam-robust-toolboxes = [color=blue][head=1] delivery-spam-1 = Robust Toolbox - Special Offer!
.desc = An advertisement for robust toolboxes.
.content = [color=blue][head=1]
░░▄▀░░ ░░▄▀░░
░▄█▄▄▀ [head=3]ROBUST - TOOLBOXES AND TOOLS[/head] ░▄█▄▄▀ [head=3]ROBUST - TOOLBOXES AND TOOLS[/head]
██▀░░░ [/head][/color] ██▀░░░ [/head][/color]
@@ -40,13 +45,15 @@ delivery-spam-robust-toolboxes = [color=blue][head=1]
{"[bold]ALL THIS AND POSSIBLY MORE FOR ONLY ONE ORGAN![/bold]"} {"[bold]ALL THIS AND POSSIBLY MORE FOR ONLY ONE ORGAN![/bold]"}
ROBUST - TOOLBOXES AND TOOLS: ROBUST - TOOLBOXES AND TOOLS:%
-LEAD AND ASBESTOS FREE! -LEAD AND ASBESTOS FREE!
-OR WITH LEAD AND ASBESTOS, IF YOU PREFER! -OR WITH LEAD AND ASBESTOS, IF YOU PREFER!
-CHEAP! ONLY ONE ORGAN! THAT'S LESS THAN TWO ORGANS! -CHEAP! ONLY ONE ORGAN! THAT'S LESS THAN TWO ORGANS!
-DOESN'T HAVE TO BE YOUR ORGAN! WE DON'T JUDGE! -DOESN'T HAVE TO BE YOUR ORGAN! WE DON'T JUDGE!
delivery-spam-reasons-to-chose-nanotrasen = {-delivery-header-nanotrasen} delivery-spam-2 = Reasons to choose Nanotrasen!
.desc = An advertisement for Nanotrasen.
.content = {-delivery-header-nanotrasen}
{"[head=2]TOP THREE REASONS WHY THE SYNDICATE IS INCOMPETENT[/head]"} {"[head=2]TOP THREE REASONS WHY THE SYNDICATE IS INCOMPETENT[/head]"}
@@ -59,7 +66,9 @@ delivery-spam-reasons-to-chose-nanotrasen = {-delivery-header-nanotrasen}
{"[bold]NUMBER THREE[/bold]"} {"[bold]NUMBER THREE[/bold]"}
THEIR LOGO IS HORRIBLE! THEY THINK THEY'RE COOL WITH THEIR LOGO! OOH, LOOK AT ME, I'M SO COOL! OOH, SNAKE THAT'S ALSO AN S! HOW CREATIVE! MY THREE YEAR OLD SON COULD DRAW A BETTER LOGO! THEIR LOGO IS HORRIBLE! THEY THINK THEY'RE COOL WITH THEIR LOGO! OOH, LOOK AT ME, I'M SO COOL! OOH, SNAKE THAT'S ALSO AN S! HOW CREATIVE! MY THREE YEAR OLD SON COULD DRAW A BETTER LOGO!
delivery-spam-reasons-to-choose-syndicate = {-delivery-header-syndicate} delivery-spam-3 = Reasons to choose The Syndicate!
.desc = An advertisement for The Syndicate.
.content = {-delivery-header-syndicate}
{"[head=2]TOP THREE REASONS WHY NANOTRASEN IS INCOMPETENT[/head]"} {"[head=2]TOP THREE REASONS WHY NANOTRASEN IS INCOMPETENT[/head]"}
@@ -72,7 +81,9 @@ delivery-spam-reasons-to-choose-syndicate = {-delivery-header-syndicate}
{"[bold]NUMBER THREE[/bold]"} {"[bold]NUMBER THREE[/bold]"}
THEIR MURDER METHODS ARE UNINSPIRED! IT'S JUST GUN! THERE'S NO THROWING PEOPLE INTO DEEP SPACE, NO FEEDING PEOPLE INTO RECYCLERS WITH SAFETY MODE DISENGAGED, NO SLIPPING BOMBS INTO POCKETS! SO BORING! THEIR MURDER METHODS ARE UNINSPIRED! IT'S JUST GUN! THERE'S NO THROWING PEOPLE INTO DEEP SPACE, NO FEEDING PEOPLE INTO RECYCLERS WITH SAFETY MODE DISENGAGED, NO SLIPPING BOMBS INTO POCKETS! SO BORING!
delivery-spam-tired-of-science = [head=3]Science will LOVE you for this!! delivery-spam-4 = Tired of science blowing up?
.desc = Follow these simple steps to ensure it never happens again!
.content = [head=3]Science will LOVE you for this!!
are [bold]YOU[/bold] Tired of your Station's Science Department blowing up withoutdoing any actual science? are [bold]YOU[/bold] Tired of your Station's Science Department blowing up withoutdoing any actual science?
Well Your in luck![/head] Well Your in luck![/head]
@@ -88,7 +99,9 @@ delivery-spam-tired-of-science = [head=3]Science will LOVE you for this!!
{"[color=lightgray]Note: Spider Clan is not responsible for any punishment issued by your supervisors.[/color]"} {"[color=lightgray]Note: Spider Clan is not responsible for any punishment issued by your supervisors.[/color]"}
delivery-spam-free-all-access = [head=3]Have You ever wanted to have [italic][color=green]Free [bold]All Axcess!?!?[/bold][/color][/italic][/head] delivery-spam-5 = FREE ALL AXCESS!!
.desc = Did you ever want free all access?!
.content = [head=3]Have You ever wanted to have [italic][color=green]Free [bold]All Axcess!?!?[/bold][/color][/italic][/head]
{"[head=2]Well NOW YOU CAN!![/head]!"} {"[head=2]Well NOW YOU CAN!![/head]!"}
All you need to do is call [color=blue]555-GOUR-LECKSSS[/color] and state your Staton ID# !!! All you need to do is call [color=blue]555-GOUR-LECKSSS[/color] and state your Staton ID# !!!
@@ -102,7 +115,9 @@ delivery-spam-free-all-access = [head=3]Have You ever wanted to have [italic][co
{"[bullet/]Note: We at Gour-Lecksss LMT. are not responsible if your station's HoP forces you to fill out an ACTUAL Free AA form if they find out about this letter"} {"[bullet/]Note: We at Gour-Lecksss LMT. are not responsible if your station's HoP forces you to fill out an ACTUAL Free AA form if they find out about this letter"}
{"[/color]"} {"[/color]"}
delivery-spam-centcomm-retribution = [color=red] THIS IS AN OFICAL NOTICE FROM THE HEAD OF [color=blue]NANOTRASN[/color][/color] delivery-spam-6 = NOTICE FROM NANOTRASN!!
.desc = An official notice from the CEO of Nanotrasn?!
.content = [color=red] THIS IS AN OFICAL NOTICE FROM THE HEAD OF [color=blue]NANOTRASN[/color][/color]
Dear Sir, Madam, or Other Insignificat station personell Dear Sir, Madam, or Other Insignificat station personell
@@ -112,7 +127,9 @@ delivery-spam-centcomm-retribution = [color=red] THIS IS AN OFICAL NOTICE FROM T
{"[head=2][color=red]IGNORE THIS ORDER AT RISK OF RETRIBUTON FROM [color=green]CENTCO[/color]!!!!![/head][/color]"} {"[head=2][color=red]IGNORE THIS ORDER AT RISK OF RETRIBUTON FROM [color=green]CENTCO[/color]!!!!![/head][/color]"}
delivery-spam-alternate-timeline = {-delivery-header-nanotrasen-alternate-timeline} delivery-spam-7 = Send reinforcements!
.desc = An official notice from... an alternate timeline?
.content = {-delivery-header-nanotrasen-alternate-timeline}
{"[head=2]This is an official notice from the [color=red]Chief Security Officer[/color] at a Nanotrasen's Space Station 15.[/head]"} {"[head=2]This is an official notice from the [color=red]Chief Security Officer[/color] at a Nanotrasen's Space Station 15.[/head]"}
To whoever receives this letter. I am Sergeant Rigel. My occupation is the CSO. We need immediate assistance. To whoever receives this letter. I am Sergeant Rigel. My occupation is the CSO. We need immediate assistance.
@@ -123,7 +140,9 @@ delivery-spam-alternate-timeline = {-delivery-header-nanotrasen-alternate-timeli
Glory to Nanotrasen. Glory to Nanotrasen.
delivery-spam-narsie-cult = [color=#134975][head=2]The Children of Nar'Sie[/head][/color] delivery-spam-8 = The Children of Nar'Sie
.desc = A local cult is looking for recruits.
.content = [color=#134975][head=2]The Children of Nar'Sie[/head][/color]
The Beginning of a New Era The Beginning of a New Era
{"[bold]══──══──══──══──══──══──══──══──══──══──══[/bold]"} {"[bold]══──══──══──══──══──══──══──══──══──══──══[/bold]"}
@@ -140,7 +159,9 @@ delivery-spam-narsie-cult = [color=#134975][head=2]The C
All you have to do is say [color=#FF0000][italic]"Sas'so c'arta forbici!"[/italic][/color] All you have to do is say [color=#FF0000][italic]"Sas'so c'arta forbici!"[/italic][/color]
delivery-spam-rage-cage = [color=#aaaaaa]▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[/color] delivery-spam-9 = Do you want to fight?!
.desc = Advertisement for a local fighting club.
.content = [color=#aaaaaa]▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[/color]
{"[bold][head=1]THE RAGE CAGE[/head][/bold]"} {"[bold][head=1]THE RAGE CAGE[/head][/bold]"}
{"[color=#aaaaaa]▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬[/color]"} {"[color=#aaaaaa]▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬[/color]"}
{"[bold][color=#FF0000][head=3]DO YOU WANT TO FIGHT?[/head][/color][/bold]"} {"[bold][color=#FF0000][head=3]DO YOU WANT TO FIGHT?[/head][/color][/bold]"}
@@ -159,7 +180,9 @@ delivery-spam-rage-cage = [color=#aaaaaa]▀▀▀▀▀▀▀▀▀▀▀▀▀
────────────────────────────────────────── ──────────────────────────────────────────
No weapons, no armor, just pure unadulterated [bold]COMBAT[/bold]. Don't lose out and be a [bold]WIMP[/bold]. Win the glory of being your station's most robust fighter in the [color=#FF0000][bold]RAGE CAGE[/bold][/color] today! No weapons, no armor, just pure unadulterated [bold]COMBAT[/bold]. Don't lose out and be a [bold]WIMP[/bold]. Win the glory of being your station's most robust fighter in the [color=#FF0000][bold]RAGE CAGE[/bold][/color] today!
delivery-spam-evil-lizard = [color=#FF0000][bold][head=2]STOP[/head][/bold][/color] delivery-spam-10 = DO NOT OPEN THIS MAIL
.desc = You have been cursed!
.content = [color=#FF0000][bold][head=2]STOP[/head][/bold][/color]
If yore reading this letter...[color=#FF0000][head=3]YOUR ALRAEDY CURSED!!![/head][/color] If yore reading this letter...[color=#FF0000][head=3]YOUR ALRAEDY CURSED!!![/head][/color]
@@ -198,8 +221,9 @@ delivery-spam-evil-lizard = [color=#FF0000][bold][head=2]STOP[/head][/bold][/col
░░░░░░[color=#6EC543]████[/color]░░░░░░░░[color=#6EC543]████████[/color]░░░░░░░░ ░░░░░░[color=#6EC543]████[/color]░░░░░░░░[color=#6EC543]████████[/color]░░░░░░░░
░░░░░░░░░░░░░░░░░░░░[color=#6EC543]████[/color]░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░[color=#6EC543]████[/color]░░░░░░░░░░
delivery-spam-parents-need-money = [bold]Hello Child,[/bold] delivery-spam-11 = Help mom and dad!
.desc = Parents in need of financial support.
.content = [bold]Hello Child,[/bold]
This is your Parents writing to you: we are in need of money! Our taxes have been audited and we owe $100,000 in spesos to governnment! please help! they only want gift cards so you will need to send us 100 $1000 spesos Bisa gift cards. This is your Parents writing to you: we are in need of money! Our taxes have been audited and we owe $100,000 in spesos to governnment! please help! they only want gift cards so you will need to send us 100 $1000 spesos Bisa gift cards.
please mail to: please mail to:
@@ -213,7 +237,9 @@ delivery-spam-parents-need-money = [bold]Hello Child,[/bold]
{"[bold]thank you and we love you,[/bold]"} {"[bold]thank you and we love you,[/bold]"}
{"[italic]parents[/italics]"} {"[italic]parents[/italics]"}
delivery-spam-voyage-advertisement = [head=2]Join us on the maiden voyage of the...[/head] delivery-spam-12 = Join us on the maiden voyage!
.desc = Advertisement for a relaxing voyage.
.content = [head=2]Join us on the maiden voyage of the...[/head]
░█▀▀░█▀▀░░░█▀▄░█▀▀░█░░░█▀█░█░█░█▀█░█▀▄ ░█▀▀░█▀▀░░░█▀▄░█▀▀░█░░░█▀█░█░█░█▀█░█▀▄
░▀▀█░▀▀█░░░█▀▄░█▀▀░█░░░█▀█░▄▀▄░█░█░█▀▄ ░▀▀█░▀▀█░░░█▀▄░█▀▀░█░░░█▀█░▄▀▄░█░█░█▀▄

View File

@@ -0,0 +1,5 @@
- type: localizedDataset
id: DeliverySpamLetters
values:
prefix: delivery-spam-
count: 12

View File

@@ -1,113 +1,11 @@
### Spam Mail ### Spam Mail
## TODO: They all should be a localized dataset for PaperComponent
# Advertisements
- type: entity - type: entity
id: MailRobustToolsSpam id: MailSpamLetter
name: Robust Toolbox - Special Offer! name: spam letter
description: An advertisement for the robust toolboxes. description: Even space isn't safe from junk mail.
parent: Paper parent: Paper
components: components:
- type: Paper - type: Paper
content: delivery-spam-robust-toolboxes - type: RandomPaperContent
dataset: DeliverySpamLetters
- type: entity
id: MailNanotrasenSpam
name: Reasons to choose Nanotrasen!
description: An advertisement for the Nanotrasen.
parent: Paper
components:
- type: Paper
content: delivery-spam-reasons-to-chose-nanotrasen
- type: entity
id: MailSyndicateSpam
name: Reasons to choose The Syndicate!
description: An advertisement for the The Syndicate.
parent: Paper
components:
- type: Paper
content: delivery-spam-reasons-to-choose-syndicate
- type: entity
id: MailAlternativeDimensionSpam
name: Send reinforcements!
description: An official notice from... an alternate timeline?
parent: Paper
components:
- type: Paper
content: delivery-spam-alternate-timeline
- type: entity
id: MailNarsieCultSpam
name: The Children of Nar'Sie
description: A local cult is looking for recruits.
parent: Paper
components:
- type: Paper
content: delivery-spam-narsie-cult
- type: entity
id: MailRageCageSpam
name: Do you want to fight?!
description: Advertisement for a local fighting club.
parent: Paper
components:
- type: Paper
content: delivery-spam-rage-cage
- type: entity
id: MailVoyageAdvertisementSpam
name: Join us on the maiden voyage!
description: Advertisement for a relaxing voyage.
parent: Paper
components:
- type: Paper
content: delivery-spam-voyage-advertisement
# Scam Mail
- type: entity
id: MailScienceSpiderClanSpam
name: Tired of science blowing up?
description: Follow these simple steps to ensure it never happens again!
parent: Paper
components:
- type: Paper
content: delivery-spam-tired-of-science
- type: entity
id: MailAllAccessSpam
name: FREE ALL AXCESS!! # Spelling mistake intentional
description: Did you ever want free all access?!
parent: Paper
components:
- type: Paper
content: delivery-spam-free-all-access
- type: entity
id: MailCentcommRetributionSpam
name: NOTICE FROM NANOTRASN!! # Spelling mistake intentional
description: An official notice from the CEO of Nanotrasn?!
parent: Paper
components:
- type: Paper
content: delivery-spam-centcomm-retribution
- type: entity
id: MailEvilLizardSpam
name: DO NOT OPEN THIS MAIL
description: You have been cursed!
parent: Paper
components:
- type: Paper
content: delivery-spam-evil-lizard
- type: entity
id: MailParentsNeedMoneySpam
name: Help mom and dad!
description: Parents in need of financial support.
parent: Paper
components:
- type: Paper
content: delivery-spam-parents-need-money

View File

@@ -5,18 +5,7 @@
id: SpamMailTable id: SpamMailTable
table: !type:GroupSelector table: !type:GroupSelector
children: children:
- id: MailAllAccessSpam - id: MailSpamLetter
- id: MailAlternativeDimensionSpam
- id: MailCentcommRetributionSpam
- id: MailEvilLizardSpam
- id: MailNanotrasenSpam
- id: MailNarsieCultSpam
- id: MailParentsNeedMoneySpam
- id: MailRageCageSpam
- id: MailRobustToolsSpam
- id: MailScienceSpiderClanSpam
- id: MailSyndicateSpam
- id: MailVoyageAdvertisementSpam
# Letter Bundles # Letter Bundles
## Basically items that should always spawn together, specific to letters ## Basically items that should always spawn together, specific to letters

View File

@@ -578,3 +578,17 @@ ToxinChemistryBottle: ChemistryBottleToxin
# 2025-03-29 # 2025-03-29
ClothingBackpackDuffelSyndicateRaidBundle: ClothingBackpackSyndicateRaidBundle ClothingBackpackDuffelSyndicateRaidBundle: ClothingBackpackSyndicateRaidBundle
# 2025-04-14
MailRobustToolsSpam: MailSpamLetter
MailNanotrasenSpam: MailSpamLetter
MailSyndicateSpam: MailSpamLetter
MailAlternativeDimensionSpam: MailSpamLetter
MailNarsieCultSpam: MailSpamLetter
MailRageCageSpam: MailSpamLetter
MailVoyageAdvertisementSpam: MailSpamLetter
MailScienceSpiderClanSpam: MailSpamLetter
MailAllAccessSpam: MailSpamLetter
MailCentcommRetributionSpam: MailSpamLetter
MailEvilLizardSpam: MailSpamLetter
MailParentsNeedMoneySpam: MailSpamLetter