Notes
Notes - notes.io |
using System.Collections.Generic;
using System.Windows.Forms;
using OfficeOpenXml;
using System.IO;
using RtfPipe;
using System.Threading.Tasks;
using System.Drawing;
using System.Linq;
using System.Threading;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Text;
using MimeKit;
using MailKit.Net.Smtp;
using MailKit.Security;
using System.Net.Mail;
namespace TopluMailGonderici
{
public partial class Form1 : Form
{
List<(string isim, string hitap, string email)> alicilar = new List<(string, string, string)>();
List<string> attachmentPaths = new List<string>();
private CancellationTokenSource cts;
private int lastSentIndex = 0;
private string password = "md-xxx";
private string smtpHost = "smtp.mandrillapp.com";
private int smtpPort = 587;
private bool smtpSSL = true;
public Form1()
{
InitializeComponent();
}
private void btnBrowseExcel_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel Dosyaları|*.xlsx";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
lblExcelPath.Text = openFileDialog.FileName;
ExcelOku(openFileDialog.FileName);
}
}
private void ExcelOku(string dosyaYolu)
{
if (string.IsNullOrEmpty(dosyaYolu) || !File.Exists(dosyaYolu)) return;
alicilar.Clear();
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var package = new ExcelPackage(new FileInfo(dosyaYolu)))
{
var worksheet = package.Workbook.Worksheets[0];
int satirSayisi = worksheet?.Dimension?.End.Row ?? 0;
for (int i = 2; i <= satirSayisi; i++)
{
var isim = worksheet.Cells[i, 1].Text?.Trim() ?? "";
var hitap = worksheet.Cells[i, 3].Text?.Trim() ?? "";
var email = worksheet.Cells[i, 4].Text?.Trim() ?? "";
if (!string.IsNullOrEmpty(email))
alicilar.Add((isim, hitap, email));
}
}
MessageBox.Show($"{alicilar.Count} alıcı yüklendi.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
if (lblStatus != null) lblStatus.Text = $"{alicilar.Count} alıcı yüklendi.";
}
private void btnAttachment_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Multiselect = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
attachmentPaths.Clear();
attachmentPaths.AddRange(openFileDialog.FileNames);
if (lblAttachmentPath != null)
lblAttachmentPath.Text = string.Join(", ", attachmentPaths.Select(Path.GetFileName));
if (lblStatus != null)
lblStatus.Text = $"{attachmentPaths.Count} ek dosya seçildi.";
}
}
private async void btnSendEmails_Click(object sender, EventArgs e)
{
if (alicilar.Count == 0)
{
MessageBox.Show("Lütfen geçerli bir Excel dosyası seçin.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string subject = txtSubject?.Text?.Trim() ?? "";
string bodyTemplate = rtbBody?.Rtf != null ? RtfToHtml(rtbBody.Rtf) : "";
string senderEmail = txtSender?.Text?.Trim() ?? "";
string ccEmails = txtCC?.Text?.Trim() ?? "";
string bccEmails = txtBCC?.Text?.Trim() ?? "";
if (string.IsNullOrEmpty(subject) || string.IsNullOrEmpty(bodyTemplate))
{
MessageBox.Show("Lütfen konu ve içerik bilgilerini doldurun.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (rbSMTP.Checked && string.IsNullOrEmpty(senderEmail))
{
MessageBox.Show("Lütfen gönderici e-posta adresini girin.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (!string.IsNullOrEmpty(ccEmails) && !ValidateEmailAddresses(ccEmails))
{
MessageBox.Show("CC alanındaki e-posta adreslerinden biri geçersiz.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (!string.IsNullOrEmpty(bccEmails) && !ValidateEmailAddresses(bccEmails))
{
MessageBox.Show("BCC alanındaki e-posta adreslerinden biri geçersiz.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
btnSendEmails.Enabled = false;
btnPause.Enabled = true;
btnResume.Enabled = false;
btnReset.Enabled = true;
progressBar.Maximum = alicilar.Count;
progressBar.Value = 0;
lblStatus.Text = "Mailler gönderiliyor... (0%)";
cts = new CancellationTokenSource();
int gonderilen = 0;
try
{
foreach (var alici in alicilar)
{
if (cts?.Token.IsCancellationRequested ?? false)
break;
string personalizedBody = $"Merhaba {alici.isim} {alici.hitap};<br><br>{bodyTemplate}";
bool basarili = false;
if (rbSMTP.Checked)
{
basarili = await MailGonderSMTP(alici.email, subject, personalizedBody, senderEmail, ccEmails, bccEmails);
}
else
{
basarili = MailGonderOutlook(alici.email, subject, personalizedBody, ccEmails, bccEmails);
}
if (basarili)
{
gonderilen++;
}
progressBar.Value = gonderilen;
int yuzde = alicilar.Count > 0 ? (gonderilen * 100 / alicilar.Count) : 0;
lblStatus.Text = $"Gönderildi: {gonderilen}/{alicilar.Count} ({yuzde}%)";
// Mandrill gibi servislerde throttling olmaması için hafif bekleme
await Task.Delay(350, cts.Token);
}
string mesaj = cts?.Token.IsCancellationRequested ?? false
? $"Gönderim yarıda kesildi.nBaşarılı: {gonderilen}/{alicilar.Count}"
: $"Gönderim tamamlandı.nBaşarılı: {gonderilen}/{alicilar.Count}";
MessageBox.Show(mesaj, "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
LogYaz($"[CRITICAL ERROR] {ex.Message}n{ex.StackTrace}");
MessageBox.Show($"Beklenmeyen hata oluştu:n{ex.Message}", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
btnSendEmails.Enabled = true;
btnPause.Enabled = false;
btnResume.Enabled = false;
btnReset.Enabled = true;
}
}
private async Task<bool> MailGonderSMTP(string recipientEmail, string subject, string body, string senderEmail, string ccEmails, string bccEmails)
{
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("", senderEmail));
message.To.Add(new MailboxAddress("", recipientEmail)); // ← sadece bu kişi To'da
message.Headers.Add("X-MC-PreserveRecipients", "true");
// CC'ler herkes tarafından görülecek
if (!string.IsNullOrWhiteSpace(ccEmails))
{
var ccList = ccEmails.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(e => e.Trim())
.Where(e => !string.IsNullOrWhiteSpace(e));
foreach (var cc in ccList)
{
message.Cc.Add(new MailboxAddress("", cc));
}
}
// BCC'ler kimseye görünmeyecek
if (!string.IsNullOrWhiteSpace(bccEmails))
{
var bccList = bccEmails.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(e => e.Trim())
.Where(e => !string.IsNullOrWhiteSpace(e));
foreach (var bcc in bccList)
{
message.Bcc.Add(new MailboxAddress("", bcc));
}
}
message.Subject = subject;
var bodyBuilder = new BodyBuilder
{
HtmlBody = body
};
foreach (string attachmentPath in attachmentPaths)
{
if (string.IsNullOrEmpty(attachmentPath) || !File.Exists(attachmentPath))
continue;
string originalFileName = Path.GetFileName(attachmentPath);
LogYaz($"[DEBUG] Ek dosya hazırlanıyor: {originalFileName}");
// BodyBuilder.Attachments.Add(path) MimeKit'in kendi encoding'ini kullanır
// Bu en güvenli yöntem
bodyBuilder.Attachments.Add(attachmentPath);
}
message.Body = bodyBuilder.ToMessageBody();
using (var client = new MailKit.Net.Smtp.SmtpClient())
{
await client.ConnectAsync(smtpHost, smtpPort,
smtpSSL ? SecureSocketOptions.StartTls : SecureSocketOptions.None,
cts.Token);
await client.AuthenticateAsync(senderEmail, password, cts.Token);
await client.SendAsync(message, cts.Token);
await client.DisconnectAsync(true, cts.Token);
}
LogYaz($"[SMTP BAŞARILI] To: {recipientEmail} | CC: {ccEmails} | BCC: {bccEmails}");
return true;
}
catch (Exception ex)
{
LogYaz($"[SMTP HATA] To: {recipientEmail} → {ex.Message}");
// İstersen burada MessageBox gösterme, sadece logla
return false;
}
}
private bool MailGonderOutlook(string recipientEmail, string subject, string body, string ccEmails, string bccEmails)
{
try
{
Outlook.Application outlookApp = new Outlook.Application();
Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.To = recipientEmail;
mailItem.Subject = subject;
mailItem.HTMLBody = body;
if (!string.IsNullOrEmpty(ccEmails))
mailItem.CC = ccEmails;
if (!string.IsNullOrEmpty(bccEmails))
mailItem.BCC = bccEmails;
foreach (string attachmentPath in attachmentPaths)
{
if (!string.IsNullOrEmpty(attachmentPath) && File.Exists(attachmentPath))
{
string originalFileName = Path.GetFileName(attachmentPath);
string sanitizedFileName = SanitizeFileName(originalFileName);
string tempFilePath = Path.Combine(Path.GetTempPath(), sanitizedFileName);
File.Copy(attachmentPath, tempFilePath, true);
mailItem.Attachments.Add(tempFilePath, Outlook.OlAttachmentType.olByValue, 1, sanitizedFileName);
try { File.Delete(tempFilePath); } catch { }
}
}
mailItem.Send();
LogYaz($"[OUTLOOK BAŞARILI] To: {recipientEmail} | CC: {ccEmails} | BCC: {bccEmails}");
return true;
}
catch (Exception ex)
{
LogYaz($"[OUTLOOK HATA] To: {recipientEmail} → {ex.Message}");
return false;
}
}
// ────────────────────────────────────────────────
// Aşağıdaki metodlar değişmedi — olduğu gibi bırakıyorum
// ────────────────────────────────────────────────
private bool ValidateEmailAddresses(string emailString)
{
if (string.IsNullOrEmpty(emailString)) return true;
var emails = emailString.Split(',', (char)StringSplitOptions.RemoveEmptyEntries)
.Select(email => email.Trim())
.Where(email => !string.IsNullOrEmpty(email));
foreach (var email in emails)
{
try
{
var addr = new MailAddress(email);
}
catch
{
return false;
}
}
return true;
}
private string SanitizeFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName)) return fileName;
var replacements = new Dictionary<char, char>
{
{'İ', 'I'}, {'ı', 'i'}, {'Ğ', 'G'}, {'ğ', 'g'},
{'Ü', 'U'}, {'ü', 'u'}, {'Ş', 'S'}, {'ş', 's'},
{'Ö', 'O'}, {'ö', 'o'}, {'Ç', 'C'}, {'ç', 'c'},
{' ', '_'}
};
var sb = new StringBuilder();
foreach (char c in fileName)
{
sb.Append(replacements.ContainsKey(c) ? replacements[c] : c);
}
string extension = Path.GetExtension(sb.ToString());
string nameWithoutExtension = Path.GetFileNameWithoutExtension(sb.ToString());
nameWithoutExtension = nameWithoutExtension.Replace('.', '_');
return nameWithoutExtension + extension;
}
private string RtfToHtml(string rtfText)
{
return rtfText != null ? Rtf.ToHtml(rtfText) : "";
}
private void LogYaz(string mesaj)
{
string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "MailLog.txt");
using (StreamWriter sw = new StreamWriter(logPath, true, Encoding.UTF8))
{
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {mesaj}");
}
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (System.Drawing.FontFamily font in System.Drawing.FontFamily.Families)
{
if (cmbFont != null) cmbFont.Items.Add(font.Name);
}
if (cmbFont != null) cmbFont.SelectedIndex = cmbFont.Items.IndexOf("Arial");
int[] fontSizes = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 36, 48, 72 };
foreach (int size in fontSizes)
{
if (cmbFontSize != null) cmbFontSize.Items.Add(size.ToString());
}
if (cmbFontSize != null) cmbFontSize.SelectedIndex = cmbFontSize.Items.IndexOf("12");
if (lblStatus != null) lblStatus.Text = "Hazır";
rbSMTP.Checked = true;
txtSender.Text = "[email protected]";
}
private void btnBold_Click(object sender, EventArgs e)
{
if (rtbBody != null && rtbBody.SelectionFont != null)
{
System.Drawing.Font currentFont = rtbBody.SelectionFont;
FontStyle newStyle = currentFont.Bold ? currentFont.Style & ~FontStyle.Bold : currentFont.Style | FontStyle.Bold;
rtbBody.SelectionFont = new System.Drawing.Font(currentFont.FontFamily, currentFont.Size, newStyle);
}
}
private void btnItalic_Click(object sender, EventArgs e)
{
if (rtbBody != null && rtbBody.SelectionFont != null)
{
System.Drawing.Font currentFont = rtbBody.SelectionFont;
FontStyle newStyle = currentFont.Italic ? currentFont.Style & ~FontStyle.Italic : currentFont.Style | FontStyle.Italic;
rtbBody.SelectionFont = new System.Drawing.Font(currentFont.FontFamily, currentFont.Size, newStyle);
}
}
private void btnUnderline_Click(object sender, EventArgs e)
{
if (rtbBody != null && rtbBody.SelectionFont != null)
{
System.Drawing.Font currentFont = rtbBody.SelectionFont;
FontStyle newStyle = currentFont.Underline ? currentFont.Style & ~FontStyle.Underline : currentFont.Style | FontStyle.Underline;
rtbBody.SelectionFont = new System.Drawing.Font(currentFont.FontFamily, currentFont.Size, newStyle);
}
}
private void cmbFont_SelectedIndexChanged(object sender, EventArgs e)
{
if (rtbBody != null && rtbBody.SelectionFont != null && cmbFont?.SelectedItem != null)
{
System.Drawing.Font currentFont = rtbBody.SelectionFont;
rtbBody.SelectionFont = new System.Drawing.Font(cmbFont.SelectedItem.ToString(), currentFont.Size, currentFont.Style);
}
}
private void cmbFontSize_SelectedIndexChanged(object sender, EventArgs e)
{
if (rtbBody != null && rtbBody.SelectionFont != null && cmbFontSize?.SelectedItem != null)
{
System.Drawing.Font currentFont = rtbBody.SelectionFont;
float newSize = float.Parse(cmbFontSize.SelectedItem.ToString());
rtbBody.SelectionFont = new System.Drawing.Font(currentFont.FontFamily, newSize, currentFont.Style);
}
}
private void btnColor_Click(object sender, EventArgs e)
{
if (rtbBody != null)
{
using (ColorDialog colorDialog = new ColorDialog())
{
if (colorDialog.ShowDialog() == DialogResult.OK)
{
rtbBody.SelectionColor = colorDialog.Color;
}
}
}
}
private void btnPreview_Click(object sender, EventArgs e)
{
if (alicilar.Count == 0)
{
MessageBox.Show("Lütfen önce bir Excel dosyası yükleyin.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string subject = txtSubject?.Text?.Trim() ?? "";
string bodyTemplate = rtbBody?.Rtf != null ? RtfToHtml(rtbBody.Rtf) : "";
if (string.IsNullOrEmpty(subject) || string.IsNullOrEmpty(bodyTemplate))
{
MessageBox.Show("Lütfen konu ve içerik bilgilerini doldurun.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
using (Form selectionForm = new Form
{
Text = "Alıcı Seç",
Size = new Size(300, 150),
StartPosition = FormStartPosition.CenterParent,
FormBorderStyle = FormBorderStyle.FixedDialog,
MaximizeBox = false,
MinimizeBox = false
})
{
ComboBox cmbAlicilar = new ComboBox
{
Location = new Point(10, 10),
Width = 260,
DropDownStyle = ComboBoxStyle.DropDownList
};
foreach (var alici in alicilar)
{
cmbAlicilar.Items.Add($"{alici.isim} {alici.hitap} - {alici.email}");
}
cmbAlicilar.SelectedIndex = 0;
Button btnOk = new Button
{
Text = "Ön İzleme",
Location = new Point(100, 60),
Width = 80,
DialogResult = DialogResult.OK
};
selectionForm.Controls.Add(cmbAlicilar);
selectionForm.Controls.Add(btnOk);
selectionForm.AcceptButton = btnOk;
if (selectionForm.ShowDialog(this) == DialogResult.OK)
{
int selectedIndex = cmbAlicilar.SelectedIndex;
var secilenAlici = alicilar[selectedIndex];
string personalizedBody = $"Merhaba {secilenAlici.isim} {secilenAlici.hitap};<br><br>{bodyTemplate}";
Form previewForm = new Form
{
Text = "Mail Ön İzleme",
Size = new Size(600, 400),
StartPosition = FormStartPosition.CenterParent
};
WebBrowser webBrowser = new WebBrowser
{
Dock = DockStyle.Fill,
DocumentText = $"<html><head><title>{subject}</title></head><body><h2>{subject}</h2>{personalizedBody}</body></html>"
};
previewForm.Controls.Add(webBrowser);
previewForm.ShowDialog(this);
}
}
}
private void btnPause_Click(object sender, EventArgs e)
{
if (cts != null && !cts.IsCancellationRequested)
{
cts.Cancel();
btnPause.Enabled = false;
btnResume.Enabled = true;
}
}
private void btnResume_Click(object sender, EventArgs e)
{
btnResume.Enabled = false;
btnPause.Enabled = true;
btnSendEmails_Click(sender, e); // basit resume — baştan başlar
}
private void btnReset_Click(object sender, EventArgs e)
{
if (cts != null && !cts.IsCancellationRequested)
{
cts.Cancel();
}
alicilar.Clear();
attachmentPaths.Clear();
lastSentIndex = 0;
cts = null;
txtSubject.Text = "";
txtSender.Text = "[email protected]";
txtCC.Text = "";
txtBCC.Text = "";
rtbBody.Text = "Mail içeriğini buraya yazın...";
lblExcelPath.Text = "Dosya seçilmedi";
lblAttachmentPath.Text = "Dosya seçilmedi";
progressBar.Value = 0;
progressBar.Maximum = 100;
lblStatus.Text = "Hazır";
btnSendEmails.Enabled = true;
btnPause.Enabled = false;
btnResume.Enabled = false;
btnReset.Enabled = false;
rbSMTP.Checked = true;
}
}
}
![]() |
Notes is a web-based application for online taking notes. You can take your notes and share with others people. If you like taking long notes, notes.io is designed for you. To date, over 8,000,000,000+ notes created and continuing...
With notes.io;
- * You can take a note from anywhere and any device with internet connection.
- * You can share the notes in social platforms (YouTube, Facebook, Twitter, instagram etc.).
- * You can quickly share your contents without website, blog and e-mail.
- * You don't need to create any Account to share a note. As you wish you can use quick, easy and best shortened notes with sms, websites, e-mail, or messaging services (WhatsApp, iMessage, Telegram, Signal).
- * Notes.io has fabulous infrastructure design for a short link and allows you to share the note as an easy and understandable link.
Fast: Notes.io is built for speed and performance. You can take a notes quickly and browse your archive.
Easy: Notes.io doesn’t require installation. Just write and share note!
Short: Notes.io’s url just 8 character. You’ll get shorten link of your note when you want to share. (Ex: notes.io/q )
Free: Notes.io works for 14 years and has been free since the day it was started.
You immediately create your first note and start sharing with the ones you wish. If you want to contact us, you can use the following communication channels;
Email: [email protected]
Twitter: http://twitter.com/notesio
Instagram: http://instagram.com/notes.io
Facebook: http://facebook.com/notesio
Regards;
Notes.io Team
