Skip to content

Instantly share code, notes, and snippets.

@rpbeukes
Last active July 13, 2021 00:25
Show Gist options
  • Save rpbeukes/766aa2a0198e5ddf1ccce4a0d4b6734c to your computer and use it in GitHub Desktop.
Save rpbeukes/766aa2a0198e5ddf1ccce4a0d4b6734c to your computer and use it in GitHub Desktop.
Redact/Mask the email address eg: some@gmail.com => s**e@g****.com
/// <summary>
/// Redact/Mask the email address eg: some@gmail.com => s**e@g****.com
/// </summary>
public class EmailRedactor
{
/// <summary>
/// eg: "some@gmail.com" => "s**e@g****.com"
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
public string Redact(string email)
{
try
{
if (string.IsNullOrWhiteSpace(email))
return email;
// look for first occurrence of '@' in email
char[] chDelimiter = { '@' };
var split = email.Split(chDelimiter, 2);
string redactedEmail = null;
if (split.Length == 2)
{
// the '@' was detected and we have a split of 2 parts
var emailName = split[0];
var domain = split[1];
string domainExtension = null;
// find th last '.' as part of the domain
if (domain.LastIndexOf('.') >= 0)
{
// found the last occurrence of '.'
domainExtension = domain.Substring(domain.LastIndexOf('.')); // eg: "domain.com" => ".com"
// remove the domain extention from the existing domain string eg: "domain.com" => "domain"
domain = domain.Substring(0, domain.Length - domainExtension.Length);
}
// everything before left of '@'
redactedEmail = emailName[0].ToString(); // first letter of email name
// add the '*'
redactedEmail += emailName.Length >= 2 ? new string('*', emailName.Length - 2)
: string.Empty;
redactedEmail += emailName.Length > 1 ? emailName[emailName.Length - 1].ToString()
: string.Empty;
redactedEmail += '@';
// everything right of '@'
redactedEmail += domain[0]; // first letter of domain
redactedEmail += new string('*', domain.Length - 1); // fill up with '*'
redactedEmail += (domainExtension ?? string.Empty); // add domain extension if available
}
if (redactedEmail != null)
{
if (redactedEmail == email)
{
// redacting rules were missed somehow, just return some sort of redacting
return CreateDefaultRedactEmail(email);
}
// all good, return the redacted email
return redactedEmail;
}
// somehow this rules did not do what is expected, so at least return something instead of the real email
return CreateDefaultRedactEmail(email);
}
catch (Exception ex)
{
return CreateDefaultRedactEmail(email);
}
private string CreateDefaultRedactEmail(string email)
{
// these are cut down versions of redacting as they are unlikely to occur
// no '@' was detected
if (email.Length == 1)
return "*"; // good luck in knowing if this is the users email
else if (email.Length == 2)
return email[0].ToString() + new string('*', email.Length - 1);
else if (email.Length >= 3)
// This will happen if we don't know how to handle the email
// eg: s@l.com", "s*****m
return email[0].ToString() + new string('*', email.Length - 2) + email[email.Length - 1].ToString();
return "???@???";
}
}
/*
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using System;
namespace Tests.Redactors
{
[TestClass]
public class EmailRedactorTests
{
EmailRedactor _emailRedactor = new EmailRedactor();
[TestMethod]
[DataTestMethod]
[DataRow("", "")]
[DataRow(" ", " ")]
[DataRow(null, null)]
// expected out come when email contains '@' and '.', all following the rule...
// reveal the first char of the email sting, also reveal the characters left and right of the '@', and reveal the full domain extension.
[DataRow("some@gmail.com", "s**e@g****.com")]
[DataRow("s@192.168.0.1", "s@1********.1")] // https://stackoverflow.com/questions/31806538/how-to-do-masking-hiding-email-address-in-c-sharp
[DataRow("s@gmail.com", "s@g****.com")]
[DataRow("some@l.com", "s**e@l.com")]
[DataRow("s@l.com", "s*****m")] // after redacting executed, this pattern will reveal the email anyway, hence the `s*****m` pattern.
[DataRow("s@l.i", "s***i")] // same test as above, just testing the minimum number of characters
[DataRow("aa@b", "a**b")] // same test as above, just testing different pattern
[DataRow("some@.com", "s*******m")] // seems like an invalid email anyway
[DataRow("s@.it", "s***t")] // seems like an invalid email anyway
[DataRow("some@email", "s**e@e****")]
[DataRow("a@bb", "a@b*")]
// not likely email address
[DataRow("a", "*")]
[DataRow("ab", "a*")]
[DataRow("abc", "a*c")]
[DataRow("someE", "s***E")]
[DataRow("something@new.to.try.out", "s*******g@n*********.out")]
public void Redact_Emails(string emailInput, string expectedOutput)
{
_emailRedactor.Redact(emailInput).ShouldBe(expectedOutput);
}
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment