Here is my code:
trigger bi_WebToCaseLead on Case (before insert) {
Set<String> setCampaignMail = new Set<String>();
//List<CampaignMember> listCm = [SELECT Id,Lead.Email,LeadId,ContactId,Contact.Name,Contact.Email,CampaignId FROM CampaignMember WHERE Campaign.IsActive = true];
List<CampaignMember> listAg = [SELECT Id,Lead.Email,LeadId,ContactId,Contact.Name,Contact.Email,CampaignId FROM CampaignMember WHERE Campaign.IsActive = true AND (Lead.Email IN :setCampaignMail OR Contact.Email IN :setCampaignMail)];
for(CampaignMember cm : listAg){
for(Case caso : Trigger.new){
if(!setCampaignMail.contains(caso.SuppliedEmail)){
setCampaignMail.add(caso.SuppliedEmail);
}
if(caso.ChaveCampanha__c != null && cm.CampaignId.equals(caso.ChaveCampanha__c)){
cm.Status = 'Respondido';
caso.RelacionamentoLead__c = cm.LeadId;
}
}
}
update listAg;
}

trigger bi_WebToCaseLead on Case (before insert) {
Set<String> setCampaignMail = new Set<String>();
for(Case caso : Trigger.new){
if(!setCampaignMail.contains(caso.SuppliedEmail) && caso.SuppliedEmail != null){
setCampaignMail.add(caso.SuppliedEmail);
}
List<CampaignMember> listAg = [SELECT LeadId, Lead.Email, Contact.Email FROM CampaignMember WHERE Campaign.IsActive = true AND (Lead.Email IN :setCampaignMail OR Contact.Email IN :setCampaignMail)];
Map<string,Id> emailToCM = new Map<string,CampaignMember>();
for(CampaignMember cm : listAg){
//I am assuming that Lead.Email takes precedence over Contact.Email if a CampaignMember has both, but I don't know what you want here
string email;
if(cm.Lead.Email != null)
{
email = cm.Lead.Email;
}
else if(cm.Contact.Email != null)
{
email = cm.Contact.Email;
}
if(!(emailToCM.ContainsKey(email)) && email != null)
{
emailToCM.Add(email,cm);
}
}
List<CampaignMember> campaignMembersToUpdate = new List<CampaignMember>();
for(Case caso: Trigger.new)
{
CampaignMember cm = emailToCM.Get(case.SuppliedEmail);
if(caso.ChaveCampanha__c != null && cm.CampaignId.equals(caso.ChaveCampanha__c))
{
cm.Status = 'Respondido';
campaignMembersToUpdate.Add(cm);
caso.RelacionamentoLead__c = cm.LeadId;
}
}
}
}
I wrote this in notepad so there might be some syntax error somewhere. Get the set of SuppliedEmail(s) by iterating through all the cases. Use that set to query for the campaign members. Map the SuppliedEmail values to the CampaignMembers and store that in a Map. Then iterate through the cases again and look up the associated CampaignMember in the map.
One caution is this - you aren't going to be able to add the CaseId to the CampaignMember. I don't know if you were planning to, but the case Id values will be null since this is a before trigger. If you need to update CampaignMember with the Id of the case then you need to change your approach so that update happens in an after trigger.