메뉴
HN
Hacker News 49일 전

MS 이메일 수신 차단 원인과 해결 과정

IMP
7/10
핵심 요약

2026년 2월, 정상적인 이메일 발송 기술을 준수했음에도 Microsoft 이메일 서버에서 특정 IP를 차단하는 대규모 문제가 발생했습니다. 저자는 Microsoft의 SNDS(Smart Network Data Services)와 지원 포털을 활용해 원인을 분석하고, 고객에게 안내 메시지를 제공하는 등 비즈니스 영향을 최소화하기 위한 실무적 대응 과정을 공유합니다. 이 사례는 타 서비스(MS)의 불량 처리(Ban)로 인해 합법적인 발신자도 피해를 볼 수 있다는 점을 보여줍니다.

번역된 본문

← 뒤로 2026-04-12 Microsoft 사용자에게 이메일 발송 문제 해결하기

2026년 2월 24일, 우리가 보낸 이메일을 받지 못했다는 사용자 불만이 급증하는 것을 발견했습니다. 불만을 제기한 사용자들의 공통점은 모두 Microsoft를 이메일 제공자로 사용하고 있다는 것이었습니다. 이전에 이런 상황을 겪어본 적이 없었기 때문에, 저의 첫 번째 반응은 세부 정보를 확인하기 위해 Sendgrid 로그를 확인하는 것이었습니다. 로그에 따르면, Hotmail, Live, MSN, Outlook 이메일 주소로 보낸 메일들이 '지연(Deferred)' 처리되고 있었습니다. 반면 다른 이메일 주소로는 정상적으로 메일이 전송되고 있었습니다.

더 자세히 파고든 결과, Sendgrid는 이 지연에 대해 다음과 같은 사유를 보여주었습니다:

451 4.7.650 메일 서버 [redacted]이(가) IP 평판으로 인해 일시적인 속도 제한(Rate Limited)을 받았습니다. 이메일 전송 정보는 https://aka.ms/postmaster (S775) [Name=Protocol Filter Agent][AGT=PFA][MxId=redacted]를 참조하세요.

이것은 더 많은 의문을 낳았습니다. 첫째, Microsoft 사용자에게 단 1개의 이메일도 배달되지 않고 있었습니다. 이것은 단순한 '일시적인 속도 제한'이 아니었습니다. 사실상 일시적인 차단(Ban)에 가까웠습니다. 얼마나 오래 지속될까요? 명확하지 않았습니다. 그리고 IP 평판 때문이라고요? Sendgrid는 전송 평판이 99%라고 표시하고 있었습니다. Gmail Postmaster Tools를 열어보니 스팸 비율도 정상으로 보였습니다. 저는 SPF, DKIM, DMARC와 관련된 모든 모범 사례를 준수하고 있었고, 최근에 이메일 설정을 변경한 적도 없었습니다.

이 오류 코드에 대해 빠르게 구글 검색을 해보니 다음 글을 찾을 수 있었습니다: https://learn.microsoft.com/en-us/answers/questions/5786144/all-sending-ips-temporarily-rate-limited-451-4-7 . 흥미롭게도 이 글은 24시간도 채 되지 전에 게시된 것이었습니다. 저만 이 문제를 겪고 있는 게 아니었습니다. 이를 통해 저는 문제가 Microsoft에 있으며, 저에게 있는 것이 아니라고 확신하게 되었습니다. 시스템 중단(Outage)이나 잘못된 설정(Misconfiguration)으로 인해 합법적인 발신자가 불이익을 받고 있다고 생각했습니다. 분명 시간이 지나면 자연스럽게 해결될 것입니다...

이메일 도달 가능성(Deliverability)은 우리 비즈니스의 원활한 운영에 매우 중요합니다. 우리는 한 달에 약 35만 통의 이메일을 보내며, 그중 약 3만 9천 통은 거래(Transactional) 성격(로그인, 청구, 비밀번호 재설정 등)입니다. 현재 모든 이메일은 거래용인지 여부에 관계없이 두 개의 전용 IP에서 전송됩니다. 그리고 두 IP 모두 속도 제한을 받고 있었습니다.

Helpscout에는 불만이 쏟아지고 있었습니다. 저는 먼저 CX(고객 경험) 담당자들에게 사용자들을 안심시키기 위해 저장된 답변을 만들라고 지시했습니다. 다행히도 Helpscout를 통해 보낸 이메일은 우리의 Sendgrid IP를 거치지 않습니다.

안녕하세요 {%customer.firstName,fallback=there%}님, Microsoft가 일부 이메일 전송을 제한(Throttling)하고 있어, 이메일이 제때 받은 편지함에 도달하지 못하고 있는 것으로 보입니다. 24시간 정도 기다려 보시는 것을 권장합니다. 그 후에도 이메일을 받지 못하셨다면 답장해 주시기 바랍니다. 불편을 드려 죄송합니다.

이것이 결국에는 해결될 Microsoft의 문제라고 굳게 믿었음에도 불구하고, 이런 일이 발생하고 있다는 사실을 알고 편히 쉴 수 없었습니다. 그래서 저는 Microsoft 사용자에 대한 이메일 도달 가능성에 대한 연구에 바빴습니다. 저는 이런 위기의 시기에 많은 이메일 도달 가능성의 특이점들을 알게 되었습니다. 이번에는 Microsoft가 Gmail과 같은 다른 이메일 제공자들에 비해 매우 민감(Hypersensitive)하다는 평판을 가지고 있다는 것을 배웠습니다.

저는 또한 Gmail Postmaster Tools의 Microsoft 버전인 SNDS(Smart Network Data Services)에 대해 알게 되었고 즉시 계정을 만들었습니다. 이를 통해 Microsoft 관점에서 제 IP의 평판을 확인할 수 있었습니다. 예상대로 모든 것이 정상이었습니다. 불만율은 0.1% 미만이었고, 사건 발생 전 며칠 동안 모두 녹색 상자(Green boxes)로 표시되어 빨간 깃발(Red flags)이 없었습니다. 이것은 저에게 이것이 Microsoft의 문제라는 것을 더욱 확신시켰습니다.

그럼에도 불구하고, 어떤 신비로운 내면의 추동력이 저로 하여금 문제를 해결하거나 차단을 해제하기 위해 Microsoft에 맡기고 포기하는 것을 허락하지 않았습니다. 제 사이트의 충성스러운 사용자들이 영향을 받고 있다는 사실, 그리고 제가 즉시 해결할 수 없다는 것에 괴로웠습니다.

다음 단계로, 저는 지원 포털(https://olcsupport.office.com/)을 통해 Microsoft에 이메일을 보냈습니다. Sendgrid 로그의 일부를 포함하여 가능한 한 많은 관련 정보를 포함하도록 했습니다. 이 과정은 또한 제가 문제에 대한 이해를 명확히 하도록 강제했습니다. 저는 곧 답장을 받을 수 있을 것이라는 큰 기대 없이 제출 버튼을 눌렀습니다.

모든 증거를 수집하고 해당 티켓을 제출하는 과정은 제가 이전에 무시했던 것에 주의를 기울이게 했습니다. 그 err

원문 보기
원문 보기 (영어)
← back 2026-04-12 Troubleshooting Email Delivery to Microsoft Users On Feb 24, 2026 we started to see a rise in user complaints saying they're not receiving our emails. They all had one in thing in common: Microsoft as their email provider. Since I'd never encountered this before, my first reaction was to check my Sendgrid logs for details. According to the logs, emails to Hotmail, Live, MSN, and Outlook email addresses were being Deferred . Emails to other email addresses were flowing normally. Digging deeper, Sendgrid showed this reason for the deferral: 451 4.7.650 The mail server [redacted] has been temporarily rate limited due to IP reputation. For e-mail delivery information, see https://aka.ms/postmaster (S775) [Name=Protocol Filter Agent][AGT=PFA][MxId=redacted] This raised even more questions. First, no emails were being delivered to Microsoft users at all . It wasn't a 'temporary rate limit'. It was more like a temporary ban. For how long? Unclear. And due to IP reputation? Sendgrid showed a 99% sending reputation. I opened Gmail Postmaster Tools and the spam rate looked normal. I was following all the best practices with SPF, SKIM, and DMARC. I also hadn't made any changes to my email setup recently. A quick Google search for this error code led me to this: https://learn.microsoft.com/en-us/answers/questions/5786144/all-sending-ips-temporarily-rate-limited-451-4-7 . Interestingly, this was posted less than 24 hours ago. Seems like I wasn't alone. This led me to believe that the problem lay with Microsoft and not me; either an outage or a misconfiguration on their end was penalizing legitimate senders. Surely, it would resolve itself... Email deliverability is crucial for the smooth running of our business. We send ~350k emails per month of which ~39k emails are transactional in nature (login, billing, password reset, etc...). Currently, all these emails are sent from two dedicated IPs irrespective of whether the email is transactional or not. Both IPs were being rate limited. Complaints were flowing in on Helpscout. I first instructed my CX reps to create a saved reply to calm users down. Lucky for us, emails sent via Helpscout don't go through our Sendgrid IPs. Hi {%customer.firstName,fallback=there%}, It appears Microsoft is throttling some of our emails which is preventing the email from reaching your inbox in a timely manner. We recommend waiting for 24 hours. If you still haven't received the email, please reply back. We apologize for the inconvenience. Even though I firmly believed this was a Microsoft problem which would eventually fix itself, I couldn't rest easy knowing this was happening. So I busied myself with research about email deliverability to Microsoft users. I've picked up many email deliverability quirks during times of crisis like this. This time, I learned that Microsoft has a reputation for being hypersensitive compared to other email providers like Gmail. I also learned about SNDS , Microsoft's version of Gmail Postmaster Tools, and immediately created an account. This allowed me to confirm my IP reputation from Microsoft's perspective. As I expected, everything was normal. Complaint rate was < 0.1% and days leading up the incident showed all green boxes, no red flags. This further convinced me it was a Microsoft issue. Nevertheless, some mysterious inner drive prevented me from just resigning to Microsoft to fix the problem or lift the ban. It bothered me that loyal users of my site were being affected, and I couldn't remedy it immediately. As a next step, I emailed Microsoft via their support portal: https://olcsupport.office.com/ . I made sure to include as much relevant information as possible, including a subset of Sendgrid logs. This also forced me to clarify my understanding of the issue. I hit submit, not very optimistic that I'd hear back anytime soon. The process of gathering all the evidence and submitting that ticket brought my attention to something I had ignored earlier. The error said has been temporarily rate limited due to IP reputation . So far, I had been focused on the IP reputation part of that message. But during my research on Microsoft deliverability, I learned that senders can be rate limited for other reasons too, most notably spiky send traffic. Part of their motivation is to contain a potential threat before it does more harm. A temporary ban, like the one I was experiencing, fit into this theory. We send out a weekly personalized newsletter. We split the sends into four batches, Monday through Thursday, to spread out the traffic. Each batch is sent as fast as our system can call Sendgrid's Mail API. We don't throttle. And I confirmed with Sendgrid's support team that they don't throttle either. Is it possible Microsoft imposed a temporary ban on my IPs after it saw a sudden spike in emails originating from them? SELECT DATE_TRUNC('minute', created_at) AS minute_group, COUNT(*) FROM notifications WHERE email ~ 'hotmail|live|msn|outlook' AND DATE(created_at) <= '2026-02-25' GROUP BY 1 HAVING COUNT(*) > 0 ORDER BY 2 DESC This gave the number of emails we attempted to send to Microsoft users each minute leading up the incident. After filtering for counts < 50, here's the result: 2026-02-23 21:48:00,53 2025-11-26 15:36:00,66 2025-10-28 21:48:00,52 2025-08-05 21:51:00,54 The first row looked suspicious because it occurred right before the incident started. Before that, we hadn't sent that many emails to Microsoft users in a single minute since November 2025. By now, I had received a boilerplate response from Microsoft saying my sending IPs were fine. I responded saying things were not fine and tried my best to sound professional even though I was panicked. My CX reps were doing a great job handling the fallout on Helpscout. Sendgrid was periodically retrying deferred emails. It would continue to do so for up to 72 hours. I still had no clue how long this ban would last. The uncertainty was weighing on me. But the results of my SQL query and deliverability research convinced me that regardless of the cause, I needed a way to control my sending rate to Microsoft users. Coding is a great cure for uncertainty. It's predictable, controlled, and gives a sense of accomplishment. So I dived right into this task. I needed something simple and performant. Since Redis was already a part of my infrastructure, I decided to implement a simple Redis-backed throttler. class RedisRateLimiter(BaseRedisModel, ABC): def is_allowed(self, limit, window_seconds) -> Tuple[bool, int, float]: """ Check if action is allowed under rate limit. Returns: - allowed: bool - remaining: int - retry_after: float """ assert Redis is not None, 'Redis not configured' now = time.time() window_start = now - window_seconds # Use pipeline for atomic operations pipe = Redis.pipeline() # Remove old entries pipe.zremrangebyscore( self.cache_key, '-inf', window_start ) # Count current entries pipe.zcard(self.cache_key) # Get oldest entry timestamp pipe.zrange( self.cache_key, 0, 0, withscores=True ) results = pipe.execute() current_count = results[1] oldest_entry = results[2] if current_count < limit: # Allowed Redis.zadd( self.cache_key, {f"{now}:{id(now)}": now} ) Redis.expire( self.cache_key, window_seconds ) return True, limit - current_count - 1, 0 # Rate limited if oldest_entry: retry_after = \ (oldest_entry[0][1] + window_seconds) - now else: retry_after = window_seconds return False, 0, retry_after def count(self, window_seconds): """ Get current count. """ assert Redis is not None, 'Redis not configured' now = time.time() window_start = now - window_seconds count = Redis.zcount( self.cache_key, window_start, now ) return count I used it like follows: class IPPoolRateLimiter(RedisRateLimiter): name = 'ip-pool-rate-limiter' def send_email(recipient_email, ip_pool, ...): """ Sends email. """ def _rate_limit(name, limit, window_seconds=60): """ Rate limit helper method. """ limiter = IPPoolRateLimiter( f'{ip_pool.name}-{name}' ) whi