I'm not sure if there is any other way to deserialize the json when its key is different. When key is different it is considered as another type. You can do a work around like stripping the constant part of the Json using regex and deserialize it.
Try if this helps
    public class CommonPart
{
    [JsonProperty("action")]
    public string action { get; set; }
    [JsonProperty("timestamp")]
    public string timestamp { get; set; }
    [JsonProperty("url")]
    public object url { get; set; }
    [JsonProperty("ip")]
    public string ip { get; set; }
}
public class EmailPart
{
    public string Email { get; set; }
    public IList<CommonPart> Model { get; set; }
}
Then use a method to get the json like below
public EmailPart GetFromJson(string json)
    {
        var pattern = @"\[(.*?)\]";
        var regex = new Regex(pattern);
        var response = regex.Match(json);
        var test1GmailCom = response.Value;
        var responseModel = JsonConvert.DeserializeObject<List<CommonPart>>(test1GmailCom);
        var ex = new EmailPart();
        ex.Model = responseModel;
        var pattern2 = @"\'(.*?)\'";
        var regex2 = new Regex(pattern2);
        var email = regex2.Match(json).Value.Replace("'", string.Empty);
        ex.Email = email;
        return ex;
    }
I don't think this is the best way. It is best if you can update the Json, May be as below
{   "Data": {
      "test1@gmail.com": [
        {
          "action": "open",
          "timestamp": "2018-09-05 20:46:00",
          "url": null,
          "ip": "66.102.6.98"
        }
      ]   } }